Skip to content

Repository files navigation

Uinx

Systems programming without syntax noise

Readable indentation · ownership & borrowing · native LLVM code · no tracing GC · freestanding-first

Version Compiler Backend License GC

Uinx is an ahead-of-time systems language for kernels, drivers, embedded software, runtimes, and native applications. Its surface is intentionally Python-like; its execution model stays explicit enough for low-level work.

Copyright © 2026 ViudiraTech · Code by JiTianYu391


A small surface, a real compiler pipeline

struct Counter:
    value: i32

extend Counter:
    public func add(self: mutref Self, amount: i32) -> unit:
        self.value += amount
        return

func main() -> i32:
    var counter = new Counter(value=40)
    counter.add(2)
    return counter.value - 42

Uinx compiles directly through its own front end and MIR into LLVM IR; it is not a C/C++ transpiler.

Source
  ↓
Lexer → Parser → AST → Name Resolution / HIR
  ↓
Type + Trait Analysis
  ↓
Ownership / Borrow / Lifetime-Flow Analysis
  ↓
MIR → Optimization → LLVM IR → Object → Executable / ELF

What the language looks like

Area Canonical Uinx
Blocks indentation + :
Bindings val immutable, var mutable
Functions func name(...) -> Type:
Data struct, new, extend
Generics Name[T], func f[T](...)
Bounds [T: Copy] or where T: Copy + Send
Ownership implicit move + explicit move value
References ref T, mutref T, borrow, borrow mut
Raw pointers ptr T, mutptr T, unsafe dereference/arithmetic
Traits trait, extend Type with Trait
RAII Drop on normal scope exit for implemented forms
Unsafe unsafe func, unsafe:
C ABI extern "C" func
Assembly LLVM-backed asm()
Async async func, await
Freestanding dontneed std, need core
SMP concurrent, shared, percpu, smp

Generics without punctuation overload

Bounds can stay next to the parameter or move into a where clause when the signature gets busy:

func keep[T](value: T) -> T where T: Copy + Send:
    return value

struct Slot[T] where T: Copy:
    value: T

Copy is compiler-validated. An explicit Copy implementation is rejected when a field is not actually copyable, when it contains an exclusive mutable reference, or when the same concrete type has Drop semantics.

Ownership is visible when you want it to be

struct Packet:
    id: u64

func consume(packet: Packet) -> u64:
    return packet.id

func main() -> i32:
    val packet = new Packet(id=42)
    val owned = move packet
    consume(owned)
    return 0

Ordinary by-value use already moves non-Copy values. move is the explicit spelling for APIs and code where making transfer intent obvious is useful.

Safety model

Safe references are ref T and mutref T; raw pointers are separated behind an unsafe boundary. The borrow checker now tracks resolved HIR binding identity rather than variable spelling, so shadowed locals cannot accidentally erase or reuse another binding's ownership state.

The current checker includes:

  • non-Copy move tracking and partial move/reinitialization;
  • Rust-style precise place conflict (sibling fields disjoint, conservative index aliasing);
  • Polonius-style loan liveness (root + precise-place) with NLL expiry;
  • two-phase borrows for method receivers, function borrow mut args, and compound assignment (accepts v.push(v.len()), x += x);
  • reference provenance through bindings, aggregates, assignments, calls, method receivers, and returns;
  • branch joins plus loop/back-edge fixed-point analysis;
  • backward CFG-style liveness for non-lexical loan expiry;
  • stack-reference escape rejection through direct and aggregate returns;
  • conservative safe-reference checks across await suspension;
  • compiler-validated Copy eligibility;
  • fail-closed diagnostics if borrow dataflow cannot converge within its safety limit.
func main() -> i32:
    var value = 10
    val view = borrow mut value

    # Rejected while `view` is live:
    # value = 20

    deref view = 20
    return value - 20

unsafe is an explicit trust boundary, not a switch that disables ownership rules for safe references. Raw pointer operations, inline assembly, FFI contracts, MMIO, and other externally enforced invariants belong on the unsafe side of that boundary.

Scope of the claim: this tree has substantially stronger control-flow and provenance checking than the earlier 0.3 checker, but it does not claim formal equivalence to rustc or a mathematical proof that every possible safe Uinx program is memory-safe. See docs/RELEASE_STATUS.md for the exact verified and unverified boundary.

Control flow and computational model

func gcd(a0: u64, b0: u64) -> u64:
    var a = a0
    var b = b0
    while b != 0:
        val next = a % b
        a = b
        b = next
    return a

Uinx has mutable state, conditionals, unbounded-language-model loops, recursion, integer arithmetic, functions, and dynamically managed memory layers. That is a general-purpose/Turing-complete computational model in the usual abstract-machine sense; real executions are of course bounded by finite machine resources.

Also implemented: if / elif / else, while, integer-range for, loop, break, continue, scope, return, and pass.

need / dontneed: environment as source-level intent

Hosted program:

need std

Kernel or embedded code:

dontneed std
need core

dontneed runtime suppresses the hosted runtime archive. Direct manifest path dependencies can be excluded the same way. no_std; remains migration syntax; dontneed std is canonical.

Header files

Reusable declarations live in .uxh files and are enabled explicitly:

# math.uxh
def add(left: i32, right: i32) -> i32
# app.ux
need "math.uxh"

def add(left: i32, right: i32) -> i32:
    return left + right

def main() -> i32:
    return add(20, 22) - 42
uinxc app.ux -enable-header -I include -o app

Headers are loaded semantically rather than textually. The compiler resolves a canonical include-once identity, expands each .uxh file once, merges identical declarations, and rejects conflicting signatures or duplicate definitions. No include guard or #pragma once is needed. def is an indentation-friendly alias for func; a bodyless def is a declaration.

OS-first concurrency

dontneed std
need core
smp auto

shared var online_cpus: u64 = 0

func account_cpu() -> unit:
    online_cpus += 1
    return

public unsafe concurrent func secondary_cpu_entry() -> unit:
    account_cpu()
    return

concurrent propagates through the call graph. Only explicitly shared state and explicit atomic APIs lower to atomics — smp auto never promotes implicitly (Rust+C++20+LKMM explicit-shared model). Concurrent parameters must be safe to transfer: by-value and mutable-reference types need Send, while shared references need the pointee to be Sync. Send/Sync are derived structurally from fields and generic bounds. Raw pointers are not transferable by default; a reviewed pointer-owning wrapper can opt in with the concise unsafe send Type / unsafe sync Type marker. Concurrent access to non-shared mutable state is rejected (E0363) instead of receiving fake atomicity. For protocols that need explicit ordering:

fence acquire
fence release
fence acq_rel
fence seq_cst
compiler_fence acquire

Policies:

smp auto    explicit shared uses acquire/release/acq_rel; no implicit promotion
smp manual  same as auto for explicit state (no promotion)
smp strict  explicit shared uses seq_cst (debugging/max ordering)

Multi-field invariants are not magically made correct by independent atomics. Use a lock, per-CPU state, or an explicit protocol when the invariant spans multiple locations.

Bare-metal path

Create a starter kernel:

uinx new mykernel --kernel=x86_64
cd mykernel
uinx build --release

Also supported by the project generator:

uinx new mykernel --kernel=aarch64
uinx new mykernel --kernel=riscv64

A freestanding entry can stay compact:

dontneed std
need core
smp auto

public unsafe concurrent func kernel_main() -> unit:
    return

The generated project includes startup assembly, a linker script, a freestanding manifest, and target-specific ELF linking. Firmware/boot protocol integration is a platform decision rather than hidden compiler behavior.

Freestanding building blocks

The shipped low-level layers include implemented paths for:

  • core::mem byte copy/move/fill primitives;
  • core::ptr volatile MMIO helpers;
  • core::atomic full-width compiler-lowered atomics (AtomicU8/U16/U32/U64/Bool);
  • core::sync freestanding locks (SpinLock/TicketSpinLock/RwSpinLock/SeqLock/Once/Barrier);
  • typed raw-pointer arithmetic and dereference assignment;
  • alloc, minimal hosted facilities, and the fuller std layer where selected.
public unsafe func clear(base: mutptr u8, size: usize) -> unit:
    var i: usize = 0 as usize
    while i < size:
        deref (base + i) = 0
        i += 1 as usize
    return

Build the toolchain

Requirements: CMake, a C++20 compiler, LLVM development files, Clang for the tested host package link flow, and LLD for the bare-metal link flow.

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
ctest --test-dir build --output-on-failure

Direct compiler use:

build/uinxc source.ux --emit=check
build/uinxc source.ux --emit=obj -o source.o

Package workflow:

build/uinx new app
cd app
../build/uinx check
../build/uinx build
../build/uinx run

Main commands include new, build, run, check, test, fmt, lint, doc, fetch, and add.

Formatting

cmake --build build --target format
cmake --build build --target format-check
uinx fmt

Bootstrap status

The canonical stage-0 compiler in this repository is still C++20. The language has the control-flow and computational expressiveness needed for compiler work, but a complete Uinx implementation of the Uinx compiler is not shipped in this tree yet. Therefore this release must not be described as self-hosted.

docs/BOOTSTRAP.md defines the stage0 → stage1 → stage2 reproducibility criteria a real self-hosting release must pass. This is intentionally stated as an engineering boundary rather than hidden behind a wrapper that simply invokes the C++ compiler.

Documentation

Document Purpose
docs/LANGUAGE_SPEC.md canonical implemented grammar and semantics
docs/MEMORY_MODEL.md ownership, aliasing, atomics, SMP, fences
docs/BOOTSTRAP.md honest self-hosting/bootstrap acceptance criteria
docs/OS_DEVELOPMENT.md freestanding kernel workflow
docs/UNSAFE_AND_ASM.md unsafe boundary and inline assembly
docs/STANDARD_LIBRARY.md core / alloc / minimal / std layers
docs/VERIFICATION.md reproducible verification procedure
docs/RELEASE_STATUS.md implemented vs unverified boundaries

License

Uinx is released under the BSD 3-Clause License.

Copyright (c) 2026 ViudiraTech
Code by JiTianYu391

See LICENSE.

Uinx — readable at the surface, explicit at the machine boundary.

About

A modern AOT systems programming language with Python-like syntax, memory safety, no GC, LLVM backend, and first-class freestanding support.

Topics

Resources

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages