Skip to content

Releases: vixlang/Vix-lang

v0.4.3

19 Jun 11:00

Choose a tag to compare

Full Changelog: v0.4.2...v0.4.3

Vix Language v0.4.3 Release Notes

Release Date: June 19, 2026

Overview

Vix 0.4.3 focuses on fixing struct-related code generation bugs, improving array indexing with struct elements, and enhancing semantic analysis accuracy.

Bug Fixes

For-Range Loop

  • Fixed for-range direction bug: for (i in 1..n) now uses half-open ascending range semantics (< comparison) instead of bidirectional logic, simplifying behavior and fixing edge cases with empty ranges (e.g., 1..0 correctly executes zero iterations)

Array Indexing with Struct Elements

  • Struct element type hints: computeIndexPtr and visitIndexAssign now check pointerElementHints before falling back to getPointerElementTypeSafely, fixing type resolution when indexing arrays of structs
  • Pointer-to-struct indexing: visitIndex now correctly propagates struct type hints through PHI nodes when indexing pointer-to-struct arrays, using storageElemType for null values and GEP operations

Struct Push Operations

  • Struct push codegen: Array push() with struct values now heap-allocates the struct and stores a pointer with proper type hints, instead of attempting inline struct storage which caused LLVM type mismatches

Function Argument Passing

  • Struct-to-ptr argument conversion: Struct values are now automatically converted to pointers when passed to ptr-typed function parameters, with proper pointerElementHints tracking

Array Length Inference

  • Extended array length inference: inferArrayLengthFromArgument now handles pointer arguments, global variables, member access expressions, and index expressions for .len resolution

Semantic Analysis

  • Struct literal variable tracking: is_variable_used_in_node now correctly detects variable usage inside struct literals (e.g., State{tape: tape, ptr: 0})
  • Struct literal unused variable check: check_unused_variables_with_usage now traverses struct literal fields to avoid false "unused variable" warnings

New Regression Tests

  • test404.vix: Validates for-range edge cases — empty range 1..0, single-iteration 1..1, and normal range 1..2
  • test405.vix: Tests struct member array indexing, mutation via pointer methods, and struct field state tracking

Build System

  • Moved examples/Coreutils/echo.vix to examples/coreutils/echo.vix (lowercase directory)

Known Issues

  • Some ownership tests correctly fail (expected behavior for error detection)
  • Some import tests fail due to missing module files (not compiler bugs)

v0.4.2

18 Jun 10:45

Choose a tag to compare

Full Changelog: v0.4.1...v0.4.2

Vix Language v0.4.2 Release Notes

Release Date: June 18, 2026

Overview

Vix 0.4.2 introduces the LLVM backend for vixc0 (the self-hosted compiler), along with several compiler improvements and bug fixes.

New Features

LLVM Backend for vixc0

  • LLVM C API Integration: vixc0 now uses the LLVM C API for code generation instead of the QBE backend
  • helper.c Wrapper: A C helper file (vixc0/helper.c) wraps LLVM C API functions that require array parameters, enabling vixc to call them
  • Variable Tracking: Added global variable tracking system for LLVM IR generation, allowing proper alloca/store/load operations

Compiler Improvements

  • Void Extern Functions: The parser now supports extern "C" functions without return types (void functions)
  • Array to Ptr Conversion: Type checking now allows passing arrays to ptr parameters with implicit decay
  • -l Linker Flag: Added support for -l <lib> flag to specify additional libraries to link
  • global Keyword Fix: The global keyword can now be used as an identifier in extern declarations

vixc0 Enhancements

  • File Input: vixc0 can now read and compile .vix files directly (e.g., ./vixc0 test.vix)
  • Improved Argument Parsing: Better handling of command-line arguments with .vix file detection

Bug Fixes

Parser Fixes

  • Fixed parsing of void extern functions that caused syntax errors
  • Fixed global keyword not returning any token in the lexer

Type System Fixes

  • Fixed type checking to allow array-to-ptr implicit conversion in function arguments
  • Fixed return value handling in LLVM backend (proper load before return)

Code Generation Fixes

  • Fixed LLVM function type creation to use proper parameter arrays
  • Fixed alloca results not being tracked for subsequent store/load operations
  • Fixed LLVM API function names for LLVM 22 compatibility (LLVMBuildLoad2, LLVMBuildGEP2, LLVMBuildCall2)

Build System

  • Updated build.sh: Now compiles helper.c and links with LLVM libraries
  • LLVM Linking: Uses -l LLVM-22 to link against LLVM 22

Testing

All .vix files in the following directories have been tested:

  • examples/: 50+ example files compile successfully
  • tests/regression/: 170+ regression tests pass (some expected failures for ownership/error tests)
  • std/: All standard library modules compile successfully

Known Issues

  • Some ownership tests correctly fail (expected behavior for error detection)
  • Some import tests fail due to missing module files (not compiler bugs)
  • stdin input mode still reads from hardcoded test file (existing issue)

Contributors

  • Daweidie

v0.4.1

18 Jun 08:53

Choose a tag to compare

Full Changelog: v0.4.0...v0.4.1

Vix 0.4.1 Release Notes

Overview

Vix 0.4.1 standardizes the generic syntax by removing the <> angle bracket syntax and keeping only the :[T] bracket syntax for all generic constructs. This change resolves syntax conflicts between generic types and comparison operators, providing a cleaner and unambiguous grammar.

Breaking Changes

Removed <> Generic Syntax

The <> angle bracket syntax for generics has been completely removed. All generic constructs now use :[T] bracket syntax exclusively.

Before (removed):

// Type definitions
type Result<T, E> = Ok(T) | Err(E)
struct Box<T> { value: T }

// Function definitions
fn id<T>(x: T): T { return x }
fn add<T>(a: T, b: T): T { return a + b }

// Impl blocks
impl Box<T> {
    fn new(value: T): Box<T> { return Box:[T]{ value: value } }
}

// Function calls
let x = id<i32>(42)
let y = add<i32>(4, 6)

// Struct literals
let b = Box<i32>{ value: 10 }

// Type references
let arr: Box<i32> = b

After (required):

// Type definitions
type Result:[T, E] = Ok(T) | Err(E)
struct Box:[T] { value: T }

// Function definitions
fn id:[T](x: T): T { return x }
fn add:[T](a: T, b: T): T { return a + b }

// Impl blocks
impl Box:[T] {
    fn new(value: T): Box:[T] { return Box:[T]{ value: value } }
}

// Function calls
let x = id:[i32](42)
let y = add:[i32](4, 6)

// Struct literals
let b = Box:[i32]{ value: 10 }

// Type references
let arr: Box:[i32] = b

Migration Guide

To migrate existing code:

  1. Replace all TypeName<T> with TypeName:[T]
  2. Replace all fn name<T> with fn name:[T]
  3. Replace all impl Name<T> with impl Name:[T]
  4. Update type references from Name<T> to Name:[T]
  5. Ensure nested generics like Box<Box<i32>> become Box:[Box:[i32]]

What Changed

  • Parser: Removed 16 grammar rules for <> angle bracket syntax
  • Examples: Updated 5 example files to use :[T] syntax
  • Standard Library: Updated 4 std files to use :[T] syntax
  • Tests: Updated 37 regression test files and test_types.py to use :[T] syntax
  • Documentation: Updated release notes

Compatibility

  • The bootstrap compiler (vixc0/) already uses :[T] syntax
  • All existing code using <> syntax must be updated to compile
  • The :[T] syntax is now the only supported generic syntax

Why This Change?

  1. Eliminates Ambiguity: The <> syntax conflicted with comparison operators (<, >, <=, >=), making parsing ambiguous in some contexts
  2. Consistency: All generic constructs now use the same syntax pattern
  3. Simpler Grammar: Reduces parser complexity and shift/reduce conflicts
  4. Array Distinction: Clearly distinguishes between array types [T] and generic types Name:[T]

Known Issues

  • None reported for this change

Contributors

  • Daweidie

v0.4.0-dev

18 Jun 07:37

Choose a tag to compare

Full Changelog: v0.4.0...v0.4.0-dev

Vix 0.4.0-dev Release Notes

Overview

Vix 0.4.0-dev removes the legacy [] bracket generic syntax and standardizes on <> angle bracket syntax for all generic constructs. This is a breaking change that simplifies the language grammar and improves consistency.

Breaking Changes

Removed [] Generic Syntax

The :[T] bracket syntax for generics has been completely removed. All generic constructs now use <> angle brackets exclusively.

Before (removed):

// Type definitions
type Result:[T, E] = Ok(T) | Err(E)
struct Box:[T] { value: T }

// Function definitions
fn id:[T](x: T): T { return x }
fn add:[T](a: T, b: T): T { return a + b }

// Function calls
let x = id:[i32](42)
let y = add:[i32](4, 6)

// Struct literals
let b = Box:[i32]{ value: 10 }

// Type references
let arr: Box:[i32] = b

After (required):

// Type definitions
type Result<T, E> = Ok(T) | Err(E)
struct Box<T> { value: T }

// Function definitions
fn id<T>(x: T): T { return x }
fn add<T>(a: T, b: T): T { return a + b }

// Function calls
let x = id<i32>(42)
let y = add<i32>(4, 6)

// Struct literals
let b = Box<i32>{ value: 10 }

// Type references
let arr: Box<i32> = b

Migration Guide

To migrate existing code:

  1. Replace all :[ with < and corresponding ] with >
  2. Update type references from TypeName[T] to TypeName<T>
  3. Ensure nested generics like Box<Box:[i32]] become Box<Box<i32>>

What Changed

  • Parser: Removed 16 grammar rules for :[T] bracket syntax
  • Examples: Updated 5 example files to use <> syntax
  • Tests: Updated 32 regression test files to use <> syntax
  • Documentation: Updated release notes and compiler documentation

Compatibility

  • The standard library (std/) already uses <> syntax
  • The bootstrap compiler (vixc0/) already uses <> syntax
  • All existing code using :[T] syntax must be updated to compile

Known Issues

  • None reported for this change

Contributors

  • Daweidie

v0.4.0

18 Jun 04:43

Choose a tag to compare

Full Changelog: v0.3.3...v0.4.0

v0.3.3-dev

13 Jun 07:59

Choose a tag to compare

Full Changelog: v0.3.0...v0.3.3-dev

Vix Compiler v0.3.3-dev Release Notes

Release Date: June 13, 2026

Overview

Vix v0.3.3-dev is a development release focused on syntax modernization, ADT bug fixes, boolean type support, and compiler correctness fixes. Key changes include replacing the ref keyword with & for safe references, adding proper true/false boolean literals, fixing custom ADT constructors and match expressions, and expanding the vixc0 bootstrap compiler.

What's New

Syntax Change: ref replaced by &

The ref keyword has been replaced by the & symbol for safe references. This applies to both type annotations and expressions:

  • Type position: ref i32 is now &i32
  • Expression position: ref x is now &x
  • Mutable reference: mut ref x is now mut &x

Example:

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

fn main(): i32 {
    let x = 7
    let y = 8
    print(add(&x, &y))
    return 0
}

Proper Boolean Type

true and false are now proper boolean literals with type bool, instead of being aliases for 1 and 0 as i32:

  • true has type bool (previously i32)
  • false has type bool (previously i32)
  • Comparison operators (==, !=, <, <=, >, >=) return bool values
  • Boolean operators (and, or, !) work with bool type

Custom ADT Constructor Fixes

Fixed several bugs with custom Algebraic Data Type (ADT) constructors:

  • Payload type resolution: ADT constructors with payloads (e.g., Int(i32)) now correctly resolve the payload type from the type definition, instead of using a fresh type variable.
  • Tag value consistency: Custom ADT constructors now use the constructor index as the tag value (consistent with the parser), instead of a hash of the constructor name.
  • Match with custom ADTs: Match expressions with custom ADT constructor patterns (both simple identifiers like Red and payload patterns like Int(v)) now correctly compare tag values.
  • Function-local ADTs: ADT definitions inside functions now generate correct tag values, matching the behavior of top-level ADT definitions.
  • No-payload constructors: Simple enum constructors without payloads (e.g., Red, Green, Blue) now create proper tagged structs instead of returning raw integer values.

vixc0 Bootstrap Compiler

The vixc0 bootstrap compiler has been expanded with:

  • Multi-token lexer support for &, true, false, escape sequences
  • Expression parser with operator precedence (arithmetic, comparison, logical)
  • let statements, print statements, assignment statements
  • QBE IR codegen for expressions and basic statements

Bug Fixes

Ownership Checker

  • Copy Classification Fixes: string and struct values are no longer incorrectly treated as Copy by the Owner pass.
    • Assigning a string now moves ownership instead of silently allowing reuse of the source variable.
    • Assigning a struct that contains non-Copy data now also moves ownership as expected.
  • Removed Copy Naming Hack: Ownership no longer treats identifiers starting with an uppercase letter as implicitly Copy.
    • This closes a hole where move checks could be bypassed by variable naming alone.
  • By-Value Call Semantics: Function calls now distinguish between by-value and & arguments.
    • Non-& parameters consume non-Copy arguments.
    • & parameters are checked as borrows instead of generic reads.
  • Persistent Borrow Tracking: Borrows stored in variables now remain active across statements until the borrow variable leaves scope or is reassigned.
    • This prevents mutating a value while an outstanding borrow to it still exists.
  • Improved Borrow Source Propagation: Ownership now preserves borrow provenance through more expression forms.
    • Member access and indexing now retain the underlying borrowed base.
    • Borrow provenance is also propagated through simple expression and call-return paths needed for dangling-reference detection.
  • Indirect Dangling Reference Detection: Returning a local reference through an intermediate function call is now rejected.

Example now correctly rejected:

fn take(xs: [i32]): i32 {
    return xs[0]
}

fn main(): i32 {
    let xs = [1, 2, 3]
    print(take(xs))
    print(xs[0])
    return 0
}

Diagnostic:

error [SemanticError]: use of moved value 'xs'

Borrow stored across statements is now also rejected:

fn main(): i32 {
    let mut x = 1
    let r = mut &x
    x = 2
    print(@r)
    return 0
}

Diagnostic:

error [SemanticError]: cannot assign to 'x' while it is borrowed

Lexer & String Processing

  • Octal Escape Sequences: Added support for octal escape sequences (e.g., \033) in string literals. This enables proper handling of ANSI escape codes for terminal control.
    • Example: printf("\033[2J\033[H") now correctly outputs screen clearing sequences
    • Previously, \033 was incorrectly parsed as \0 followed by literal characters

Type Checker

  • Void Function Returns: Fixed type checking for void functions that don't have explicit return statements
    • Functions declared with void return type no longer require explicit return statements
    • Improved type inference for function bodies

Code Changes

Modified Files

  • src/parser/lexer.l: Removed ref keyword token (replaced by & symbol)
  • src/parser/parser.y: Removed REF_KW grammar rules, unified reference syntax under AMPERSAND
  • src/Ownership/Ownership.cpp: Corrected move/copy classification, call-site ownership handling, persistent borrow tracking, and dangling-reference propagation
  • src/Typeck/Typeck.cpp: Improved void function type checking
  • src/compiler/Stmts.cpp: Minor statement handling improvements
  • src/compiler/Structs.cpp: Struct processing enhancements
  • examples/*.vix: Updated all examples from ref to & syntax
  • tests/test_ownership.py: Updated test source strings for & syntax
  • tests/test_types.py: Updated test source strings for & syntax
  • tests/feat.py: Updated test source strings for & syntax
  • tests/regression/ownership_return_via_call.vix: Updated to & syntax
  • tests/regression/ownership_persistent_borrow.vix: Updated to & syntax

New Files

  • src/ed.vix: Text editor implementation in Vix language
  • src/test_cursor2.vix: Test program for cursor movement functionality
  • tests/regression/ownership_string_move.vix: Regression fixture for string move errors
  • tests/regression/ownership_struct_move.vix: Regression fixture for struct move errors
  • tests/regression/ownership_call_move.vix: Regression fixture for by-value call move semantics
  • tests/regression/ownership_persistent_borrow.vix: Regression fixture for borrow-across-statement assignment rejection
  • tests/regression/ownership_return_via_call.vix: Regression fixture for indirect dangling-reference rejection

Technical Details

Octal Escape Sequence Support

The lexer now properly handles octal escape sequences in the format \NNN where N is an octal digit (0-7):

printf("\033[2J\033[H")
printf("\033[10;5H")  // Move to row 10, column 5
printf("\033[31m")    // Set red text color

Arrow Key Handling

The editor now processes ANSI arrow key sequences:

  • Up Arrow: \033[A
  • Down Arrow: \033[B
  • Right Arrow: \033[C
  • Left Arrow: \033[D

Ownership Validation

Ownership-focused validation in this release covered:

  • Use-after-move for arrays, strings, and structs.
  • By-value function call move semantics.
  • Shared and mutable borrow conflict checks.
  • Borrow persistence across statements when a reference is stored in a variable.
  • Indirect dangling local reference detection through function returns.

Targeted validation performed:

  • Rebuilt vixc successfully with the updated src/Ownership/Ownership.cpp.
  • Ran venv/bin/pytest tests/test_ownership.py successfully.
  • Verified dedicated regression fixtures fail with the expected ownership diagnostics.

Installation

From Source

git clone https://github.com/vixlang/Vix-lang.git
cd Vix-lang
mkdir build && cd build
cmake ..
make
sudo make install

Using Pre-built Binaries

Download the appropriate binary for your platform from the releases page.

Known Issues

  • Some warnings are generated during compilation of example files (unused variables)
  • The Owner system still does not implement full non-lexical lifetimes, control-flow-sensitive move joins, or field-level partial move analysis

Upgrading

This release introduces a syntax change: the ref keyword is replaced by & for safe references. All code using ref must be updated:

  • ref T (type) → &T
  • ref x (expression) → &x
  • mut ref xmut &x

This is also intended to be source-compatible for valid programs (with the syntax update), but some code that previously compiled due to ownership-checker gaps will now be rejected.

In particular, v0.3.1 now diagnoses:

  • Reuse of moved string and struct values.
  • Reuse of non-Copy values after passing them to by-value function parameters.
  • Mutation while a borrow stored in a variable is still live.
  • Returning references to locals through simple intermediate call paths.

Contributors

  • Daweidie

Feedback

Please report any issues or feature requests on our GitHub Issues page.


For more information about the Vix programming language, visit vixlang.github.io.

v0.3.3

13 Jun 11:45

Choose a tag to compare

Full Changelog: v0.3.0...v0.3.3

Vix Compiler v0.3.3 Release Notes

Release Date: June 13, 2026

Overview

Vix v0.3.3 focuses on match expression enhancements, making match more powerful and ergonomic. Key improvements include using match as an expression, supporting member access as scrutinee, and adding multi-pattern arms with |.

What's New

Match Expression Enhancements

Match as Expression

match can now be used as an expression that returns a value:

let result = match tag {
    "int" -> 1
    "bool" -> 2
    _ -> 0
}

This enables more concise code when assigning values based on pattern matching.

Member Access as Scrutinee

Match expressions now support member access expressions as the scrutinee:

match expr.tag {
    "int" -> "integer"
    "string" -> "text"
    _ -> "other"
}

Previously, only simple identifiers and literals were supported as the scrutinee.

Multi-Pattern Arms

Match expressions now support multiple patterns separated by | (pipe) for the same arm:

match tag {
    "int" | "bool" | "string" -> "Literal"
    "ident" -> "Identifier"
    "binop" -> "BinaryExpression"
    _ -> "Unknown"
}

This desugars to OR conditions: (tag == "int") or (tag == "bool") or (tag == "string").

Bug Fixes

Member Access Scrutinee

Fixed a bug where match with member access expressions (e.g., match expr.tag { ... }) would fail at runtime. The clone_match_scrutinee function now correctly handles AST_MEMBER_ACCESS nodes.

Code Changes

Modified Files

  • src/parser/parser.y: Added match expression, member access scrutinee, and multi-pattern arm support
  • include/ast.h: Added is_multi_pattern field to assign node for multi-pattern match arms

Installation

From Source

git clone https://github.com/vixlang/Vix-lang.git
cd Vix-lang
mkdir build && cd build
cmake ..
make
sudo make install

Using Pre-built Binaries

Download the appropriate binary for your platform from the releases page.

Upgrading

This release is backward compatible. No code changes are required to upgrade from v0.3.2.

Contributors

  • Vix Language Team

Feedback

Please report any issues or feature requests on our GitHub Issues page.


For more information about the Vix programming language, visit vixlang.github.io.

v0.3.0

07 Jun 06:11

Choose a tag to compare

Full Changelog: v0.2.10...v0.3.0

Vix Language v0.3.0 Release Notes

Release Date: 2026-06-07

New Features

Lightweight Owner system

Vix v0.3.0 introduces the first version of the lightweight Owner system: a compile-time ownership and borrow checker designed to provide most of Rust-style memory safety with a much simpler language model.

The goal of this release is practical safety without Rust-level complexity:

  • Ownership transfer for non-Copy values.
  • Exclusive mutable references.
  • Shared immutable references.
  • Use-after-move detection.
  • Dangling local reference detection.
  • Copy-type inference for small/simple values.
  • Statement-scoped temporary borrows as a simplified “last use” model.

The Owner pass runs after type checking, using inferred AST type information from typecheck_program(...).

Files:

  • include/ownership.h
  • src/Ownership/Ownership.cpp
  • src/main.c
  • CMakeLists.txt

New reference syntax: ref and mut ref

References now use explicit keyword syntax instead of the old & spelling.

Immutable shared reference:

fn read(x: ref i32): i32
{
    return @x
}

fn main(): i32
{
    let value = 10
    print(read(ref value))
    return 0
}

Mutable exclusive reference:

fn inc(mut p: ref i32)
{
    @p = @p + 1
}

fn main(): i32
{
    let mut value = 10
    inc(mut ref value)
    print(value)
    return 0
}

Rules:

  • ref value creates an immutable shared borrow.
  • mut ref value creates a mutable exclusive borrow.
  • A value may have many immutable borrows in the same statement.
  • A mutable borrow cannot overlap another mutable or immutable borrow in the same statement.
  • Temporary borrows are released at the end of the statement.

The parser still maps references internally to the existing pointer AST representation, so existing code generation can continue to reuse pointer lowering.

Files:

  • src/parser/lexer.l
  • src/parser/parser.y
  • src/Ownership/Ownership.cpp

Move checking for non-Copy values

Non-Copy values are moved by ownership-transfer operations such as assignment into another variable.

Example rejected by the Owner checker:

fn main(): i32
{
    let xs = [1, 2, 3]
    let ys = xs
    return xs[0]
}

Diagnostic:

error [SemanticError]: use of moved value 'xs'

Legal last-use move:

fn take(xs: [i32]): i32
{
    return xs[0]
}

fn main(): i32
{
    let xs = [1, 2, 3]
    let ys = xs
    return take(ys)
}

Copy type inference

The Owner system uses a heuristic Copy model instead of requiring explicit user annotations.

Currently treated as Copy:

  • Integer types.
  • Floating-point types.
  • Boolean values.
  • References/pointers.
  • Function values.
  • Strings as lightweight reference-like values.
  • Struct values in the current lightweight model.
  • Small fixed-size arrays when their element type is Copy.
  • Uppercase enum-like constructors/constants.

Currently treated as non-Copy:

  • Dynamic arrays.
  • Generic application/container values by default.

This keeps common Vix code ergonomic while still catching important ownership errors around arrays, containers, references, and moves.

Dangling reference checks

The Owner checker rejects returning a reference to a local variable.

Example rejected:

fn bad(): ref i32
{
    let local = 99
    return ref local
}

Diagnostic:

error [SemanticError]: cannot return reference to local variable 'local'

Optional references

Optional references can be expressed with ?ref T.

fn maybe_ref(flag: i32, value: ref i32): ?ref i32
{
    if (flag == 0)
    {
        return None
    }
    return Some(value)
}

This provides a simple way to model “maybe a reference” without explicit lifetime annotations.

Diagnostics

Ownership diagnostics now include file, line, and column

Example:

error [SemanticError]: use of moved value 'xs'
  --> src/test.vix:15:11
   |
14 |     print(ys[0])
15 |     return xs[0]
   |           ^

Fixes:

  • Ownership errors now fall back to current_input_filename when AST nodes do not have source_file set.
  • Ownership errors now call set_location_with_column(...) before reporting.
  • Parser-generated unary reference/deref nodes now preserve source locations through create_unaryop_node_with_yyltype(...).

Files:

  • src/Ownership/Ownership.cpp
  • src/parser/parser.y

Examples and Tests

Updated examples for ref

The following examples were updated from old & reference syntax to ref:

  • examples/quicksort.vix
  • examples/swap.vix
  • examples/pointer.vix
  • examples/pointer2.vix
  • examples/nullptr.vix
  • examples/list.vix

Ownership test fixture

src/test.vix now acts as a negative Owner-system test file.

It intentionally triggers:

  • Use-after-move.
  • Duplicate mutable borrow with mut ref.
  • Returning a reference to a local variable.

It also contains legal comparison functions for:

  • Last-use move.
  • Copy values.
  • Immutable shared borrows.

Python tests

Added ownership-focused tests covering:

  • Move consumes non-Copy values.
  • Last-use move is allowed.
  • Copy values remain usable after assignment.
  • Duplicate mutable borrow is rejected.
  • Returning local references is rejected.

File:

  • tests/test_ownership.py

Updated existing test strings for ref syntax:

  • tests/test_types.py
  • tests/feat.py

Compatibility Notes

What v0.3.0 intentionally does not include

The Owner system is intentionally smaller than Rust’s ownership model.

Not included:

  • Explicit lifetime annotations such as <'a>.
  • Full non-lexical lifetime analysis.
  • Pin/Unpin.
  • Drop checking.
  • Higher-ranked trait bounds.
  • Full support for complex self-referential structures.

Current simplifications

  • Temporary borrow scopes are statement-based.
  • Function arguments are treated as read/borrowed by default for compatibility with existing Vix code.
  • The Copy model is heuristic and may evolve as the type system gains explicit Copy/Move traits.
  • References are still lowered through the existing pointer representation internally.

Validation

  • Rebuilt vixc successfully with the new Ownership.cpp compilation unit.
  • Verified src/test.vix emits the expected Owner errors.
  • Verified ownership diagnostics include real file names and columns.
  • Verified ref value permits shared immutable borrows.
  • Verified mut ref value enforces mutable borrow exclusivity.
  • Verified updated examples pass --check:
    • examples/quicksort.vix
    • examples/swap.vix
    • examples/pointer.vix
    • examples/pointer2.vix
    • examples/nullptr.vix
    • examples/list.vix
  • Verified regression sources no longer fail with ownership-specific moved/borrow diagnostics after compatibility adjustments.
  • Full Python test execution was not run in this environment because pytest is not installed.

v0.2.10

06 Jun 14:27

Choose a tag to compare

Full Changelog: v0.2.9...v0.2.10

Vix Language v0.2.10 Release Notes

Release Date: 2026-06-06

New Features

Multi-object file linking support

  • The compiler now supports linking multiple object files directly without recompilation.
  • Usage: vixc file1.o file2.o file3.o -o output
  • This enables separate compilation workflows where individual modules are compiled to .o files first, then linked together.
  • Added new vix_link_multi() API in the linker module to handle multiple input files.
  • Files: src/main.c, src/compiler/Linker/Linker.h, src/compiler/Linker/Linker.cpp

Bug Fixes

Enum type definition now accepts leading |

  • The parser now accepts an optional leading | before the first variant in type alias enum definitions.
  • This allows writing enums in a more consistent style:
    type T =
        | Int
        | Float
        | String
        | Bool
        | Unit
    
  • Previously, the first variant had to omit the |, which was inconsistent with subsequent variants.
  • File: src/parser/parser.y

Linker: removed hardcoded CRT object paths

  • Fixed the ELF linker path discovery to check file existence before adding CRT objects (crt1.o, crti.o, crtbegin.o, crtend.o, crtn.o) to the linker arguments.
  • Eliminated a redundant second call to probeSysPaths during ELF linking; the sysroot is now probed once and reused.
  • This fixes link failures on systems where the CRT objects are located in non-standard directories or where some objects are absent.
  • File: src/compiler/Linker/Linker.cpp

Validation

  • Rebuilt vixc successfully.
  • Verified enum definitions with leading | on the first variant now parse correctly.
  • Tested multi-object linking with vixc a.o b.o -o prog.

v0.2.9

06 Jun 12:12

Choose a tag to compare

Full Changelog: v0.2.8...v0.2.9

Vix Language v0.2.9 Release Notes

Release Date: 2026-05-31

Diagnostics

Array parameter value-semantics warnings

  • Added compile-time warnings for array parameters that are passed by value and then modified inside a function.
  • The compiler now warns when a copied array parameter is modified without returning the modified array, helping catch code that accidentally assumes reference semantics.
  • The compiler now warns when an array parameter length is read before modifying the copied parameter, highlighting stale-length patterns such as returning the old length after push.
  • The compiler now warns when an array parameter is never used.
  • Files: src/Typeck/Typeck.cpp, tests/test_types.py

Cleaner warning output

  • Improved warning formatting so multiline diagnostic messages render separate note lines instead of being flattened into one long line.
  • Warning headers now use a more readable warning: ... plus --> file:line:column layout.
  • Warning summaries now report the total warning count as Found N warnings.
  • Removed help text from warnings to avoid suggesting unsupported syntax or language features.
  • Files: src/utils/error.c, include/compiler.h, src/main.c

Code Generation

Global dynamic array push now writes back reallocated pointers

  • Fixed array.push(...) on global dynamic arrays so the data pointer returned by realloc is stored back into the global variable.
  • Fixed pushed struct elements so arrays such as [Point] allocate using the struct element size and store the struct value, not a pointer byte sequence.
  • This fixes programs that build a global array with repeated push calls and then iterate it with for.
  • Files: src/compiler/Funcs.cpp

Bug Fixes

For-loop numeric type promotion

  • Fixed a type mismatch error when using a for loop with a range where the start and end are different numeric types (e.g., 0 .. bytes_read where 0 is I32 and bytes_read is I64).
  • The compiler now allows implicit numeric promotion between integer and float types in range expressions.
  • Modified src/Typeck/Typeck.cpp to use promote_numeric for range bounds.
  • Modified include/unify.h to allow numeric type compatibility in unification.
  • Files: src/Typeck/Typeck.cpp, include/unify.h

Example

Given:

fn add_point(points: [Point], p: Point): i32 {
    let id = points.length
    points.push(p)
    return id
}

vixc now reports that points is copied, its mutation is lost, and the earlier length read may be stale relative to the copied mutation.

Validation

  • Rebuilt vixc successfully.
  • Verified src/test.vix emits the new array-parameter warnings.
  • Verified src/test.vix now compiles successfully (only an unused variable warning remains).
  • Verified warning output no longer emits help lines or #[warn(unused_variables)] text.
  • Verified src/test2.vix now prints the pushed global Point values instead of producing no output.
  • Verified standalone fixtures for copied-array mutation and unused array parameter warnings.
  • Python test execution could not be run in this environment because pytest is not installed.