Getting Started with Aria

Aria is a programming language built by AI, for AI. It's designed to minimize token usage during code generation while maximizing compile-time safety. This guide will get you up and running.

What is Aria?

Aria is not another general-purpose language designed for humans to type. It's a language engineered from first principles for the way AI assistants generate code:

  • Every token carries meaning — no semicolons, no boilerplate, no ceremony
  • The type system catches errors — sum types, exhaustive matching, no null, no implicit conversions
  • Effects are tracked — function signatures declare what side effects they perform
  • Concurrency is structured — tasks cannot leak, errors propagate automatically
  • Memory management is opt-in — GC by default, manual control when needed

Quick Example

Here's a complete Aria program:

mod main

use io, json

type Config {
    host: str = "localhost"
    port: u16 = 8080
    debug: bool = false
}

fn loadConfig(path: str) -> Config ! IoError {
    content := io.readFile(path)?
    json.decode[Config](content)?
}

entry {
    cfg := loadConfig("config.json") catch |e| {
        println("Using defaults: {e}")
        yield Config{}
    }
    println("Server starting on {cfg.host}:{cfg.port}")
}

Notice what's not there: no if err != nil blocks, no try/catch towers, no import paths with six slashes. Just the logic.

Key Concepts

Immutable by Default

Variables are immutable unless explicitly marked mut:

x := 42           // immutable — cannot reassign
mut count := 0    // mutable — can reassign
count = count + 1

Type Inference

Types are inferred but can be annotated:

name := "aria"          // inferred as str
port: u16 = 8080        // explicit type
const PI = 3.14159      // compile-time constant

Expression-Oriented

Everything is an expression that returns a value:

status := if online { "up" } else { "down" }

label := match count {
    0 => "none"
    1 => "one"
    n => "{n} items"
}

Error Handling

Errors are values, not exceptions. Propagate with ?, recover with catch:

// Propagate — returns error to caller
content := io.readFile(path)?

// Recover — handle inline
content := io.readFile(path) catch |e| {
    log.warn("fallback: {e}")
    yield "{}"
}

// Assert — panic if error
content := io.readFile("known-good.txt")!

Next Steps