Fly

A programming language for writing easily and quickly all types of software.

main.fly
import fly.os

main() {
    os.print("Hello, World!")
}

Fast

Built on LLVM, Fly compiles to optimised native code for all major platforms.

✍️

Simple

Clean, readable syntax designed to be easy to write and understand with no unnecessary complexity.

🛡️

Powerful

Multi-paradigm with procedural, object-oriented, and functional programming support.

Zero-copy functions, by design

In Fly every parameter is always passed by reference — no copies, ever.

Mark a parameter const to declare it as a read-only input. Leave it mutable and it becomes an output: the function writes results directly into the caller's variables.

This keeps call overhead minimal and lets LLVM optimise aggressively, regardless of what you are passing.

Read the Docs
// const = input (read-only reference)
// no const = output (written directly by the function)
calc(const int n, int result) {
    result = n * 2
}

main() {
    int x
    calc(21, x)   // x = 42
}

Error handling, rethought

Use fail to signal an error with an optional code and message. Errors propagate automatically to the caller — no explicit rethrow needed.

Wrap calls in handle to capture any error into the error variable, populated automatically. Then branch on it to decide what to do.

Read the Docs
get(const string url) {
    if (url == "") {
        fail 1, "url is empty"
    }
}

main() {
    handle {
        get("")
    }
    if (error) {
        // manage error ...
    }
}

A clean object model

Fly has three distinct building blocks: struct for pure data, class for objects with behaviour, and interface for contracts.

A struct holds fields and can extend one other struct — no virtual dispatch, no hidden cost.
A class adds virtual methods via vtable and can extend a struct and implement multiple interfaces.
An interface defines method signatures only and can extend multiple other interfaces.

Heap objects are created with new and released with delete — or left to a smart pointer to handle automatically.

Read the Docs
struct Point {
    int x
    int y
}

interface Drawable {
    draw()
}

class Circle : Point, Drawable {
    int radius
    draw() { /* render ... */ }
}

main() {
    Circle c = new Circle()
    c.radius = 5
    c.draw()
    delete c
}
process() {
    Point p = new unique Point()
    p.x = 10
    p.y = 42
}   // ← p freed automatically here

main() {
    process()   // no leaks, no delete
}

Memory management, your way

Fly gives you three ownership models — no garbage collector, no runtime overhead.

new unique grants exclusive ownership: the object is freed automatically when the variable goes out of scope.
new shared uses reference counting: the object lives as long as at least one owner exists.
new weak leaves lifetime control to you, with no counting overhead.

All three are deterministic: memory is released exactly when the scope ends, with no pauses and no surprises.

Read the Docs

Ready to fly?

Install Fly and start building today.

Install Fly