One Language.
Everything You Build.
Avlory is designing its own programming language: one language for games, apps, servers and tools, made for the Avlory Engine and Nebula first. It reads like Java, only shorter, and it keeps memory safe without a garbage collector. Designed, not built yet: there's no compiler, so nothing on this page has run. Its name comes later.
One language for every kind of program.
Games, apps, servers and tools, all from the first phase, not game scripts first. It's made for the Avlory Engine first: its early preview is planned as the simple script language in Nebula's first build, beside Rust, C# and C++.
Games
DesignedScripts in Nebula first. Players can load verified, sandboxed mods, only in games whose developer turns them on.
Apps
DesignedIts own interface framework for desktop and phone apps, not only the logic behind another toolkit.
Servers
DesignedFull multithreading and waiting code: functions marked
waits, task groups, parallel loops and plain threads.Every device
DesignedIt compiles to bytecode, as Java does. Phones and consoles that forbid making machine code at run time get it translated to native code ahead of time.
Reads like Java. Shorter.
Types come before names, as in Java. fn marks a function, var a variable and konst a constant. Semicolons are optional: a line break ends a statement, and a semicolon is still allowed. Most words with a hard c are gone: type instead of class, trap instead of catch.
Designed syntax, not yet compiled. It may change before release.
Types, constants and inheritance
class Enemy {
static final int MAX_HEALTH = 100;
int health;
}
final class Boss extends Enemy {
boolean enraged;
}konst int maxHealth = 100
open type Enemy {
int health
}
type Boss : Enemy {
bool enraged
}A type can be built on only if it's marked open, so Boss is closed unless it says otherwise.
Errors the compiler can see
SaveGame loadSave(String path)
throws SaveError { … }
try {
String text = Files.readString(Path.of(path));
} catch (IOException err) { … }fn SaveGame loadSave(str path)
throws SaveError { … }
fs.read(path) trap err { … }
// try passes the error up
var save = try loadSave(path)A function says it can fail, and with which error type. The caller handles it with trap or passes it on with try, so the compiler knows every way a program can fail.
Branches and waiting
switch (state) {
case IDLE -> rest();
case CHASING -> chase();
}
if (x instanceof Player) { … }
CompletableFuture<Scores> fetch() { … }match (state) {
is Idle: rest()
is Chasing: chase()
}
if (x is Player) { … }
fn Scores fetch() waits { … }| You know | Here | What it does |
|---|---|---|
class | type | Defines a type with fields and methods |
interface | role | What a type promises to do |
| a small value class | struct | Small values that copy when assigned |
catch | trap | Handles an error |
continue | skip | Jumps to the next round of a loop |
switch / case | match / is | Picks a branch; is also checks a type |
static final | konst | A constant or a value set once |
async (C#, JavaScript) | waits | Marks a function that waits, after its signature |
| a type alias | alias | Another name for a type |
double, float, char, String | db, flt, rune, str | Short type names, with int, long, byte and bool |
Memory, without the pain.
There's no garbage collector. Every value has one owner and is freed when its owner is done with it. The compiler checks the rules before the program ever runs, as Rust does, but the words are plainer: reading something needs no word at all, inout lets a function change it, and take hands it over for good.
Designed syntax, not yet compiled. It may change before release.
fn reload(inout Weapon w, take Magazine mag) { … }
reload(inout gun, take mag)
// gun is still yours, and now it's changed.
// mag belongs to reload now; using it again is an error.
struct Vec3 { flt x; flt y; flt z }
// small struct values copy when assignedRead: write nothing
A plain
Weapon wborrows the value to look at. Reading is the most common case, so it costs nothing to write.Change:
inoutThe function may change the value, and the call says so too, so a change never hides.
Hand over:
takeThe value belongs to the function now and is freed when it ends. Using it again afterwards is a compile error.
What ownership asks of you
- Ownership rules take some learning. The plan is errors that say what happened, where, why and how to fix it, and fewer annotations wherever the compiler can safely work them out.
- Number overflow: a debug build stops with a report; a release build wraps around, as Rust's release builds do.
Batteries included.
Libraries, imports and packages from the start, and the tools around them designed with the language, not added later.
Its own package manager
DesignedIts own package manager and registry, as pip is to Python and npm is to JavaScript.
Easy to install
DesignedInstalling sets up your path and environment itself, with one clear way to configure a project.
Sandboxed build scripts
DesignedA package may run a build script, but only in a sandbox: no network, and no files outside the package.
Documented, extensively
DesignedEverything is documented, on a docs website of its own planned from day one. English first.
Errors that explain
DesignedCompiler and run-time errors say what happened, where, why, and how to fix it.
Part of the Engine
PlannedPulse and Sprout support it, down to Sprout's language breakdown of a project, and it works with Sound.
Promises, written down now.
Decided before the first line of the compiler, so they can't be bargained away later.
Long-term support every two years
A long-term-support version every two years, with security fixes, so a shipped game can stay on its version.
Old code keeps working
Code written for any earlier version keeps compiling, and old compiled programs keep loading. Packages on different editions work together.
Open source, once proven
It opens once it's stable and Avlory has built a real project in it. Until then it stays internal.
No speed claims until measured
We won't publish speed claims until it has been tested and measured.
Designed, not built yet.
The language is being designed and decided one piece at a time. There's no compiler and no runtime yet, so there's no live demo, and none of the samples above has run. When the first build runs, this page will show it running.
Decided so far
- The words and the short type names above, with optional semicolons.
- Ownership written with
inoutandtake, and no garbage collector. - Errors declared with
throws, handled withtrapor passed on withtry. - Waiting with
waits, and full multithreading. - Types closed unless marked
open. - Long-term support every two years, and backward compatibility.
Still to come
- Its name, once a trademark search is done.
- The compiler and the runtime.
- An early preview inside Nebula's first build.
- Tests and measurements, before any speed claim.
- The docs website.
Hear When It Runs.
Its first preview is planned inside Nebula. We'll email you when there's something to try.