Beta Release 0.1.9

This release brings major syntax changes, optional semicolons, OVM-WASM support for MacOS, and a host of bugfixes in the compiler and the standard library.

Major Syntax Changes

New Keywords

In this version of Onyx there are two new keywords: in and as. They both exist to clean up the syntax of existing constructs in Onyx.

For Loops

For for loops, Onyx now uses the following syntax to avoid the confusion of the :.

for value in iterable {
    // body

This is a small change, but it is much more readable and beginner-friendly. It also enables a very useful feature of for-loop that is new in this version: indexed for-loops.

For-loop can now have an optional second variable that is the index of the loop. This variable is an i32 by default, but that can be changed using : TYPE after the variable. Note that only integer types are currently supported. Also worthy of note, is that you can now explicitly type the loop iterator, and you will get a compile error if it is typed wrong.

arr := .["A", "list", "of", "strings"];

for value: str, index: i32 in arr {
    // body

// Or more succinctly

for value, index in arr {
    // body

Case Statement Captures

For case statements with captures, Onyx now uses the following syntax. The old syntax was meant to parallel the for-loop syntax, and since that changed, I felt this needed to change as well.

switch some_union {
    case .SomeVariant as some_value {
        // body

    // Capture by pointer
    case .AnotherVariant as &another_value {
        // body


Interfaces also got some touch ups this version. Interface parameters now look like normal procedure or structure parameters, and can be of any type, so long as their value is compile-time known. To specify that you want a value of a certain type in an interface body, simply use the as keyword.

CanAdd :: interface (T: type_expr) {
    t as T;

    { t + t } -> T;

add :: (x, y: $T) -> T where CanAdd(T) {
    return x + y;

Optional Semicolons

As an experimental feature, you can now opt in to optional-semicolons. To do so, simply pass the --feature optional-semicolons flag to enable optional-semicolons across an entire project. Or, simply place the following line at the top of any Onyx file to enable optional-semicolons in that file. This line must be the first line of code.


Optional semicolons are implemented in a very straight forward way. Whenever the lexical analyzer encounters a newline, it looks at the last token it procedure and if it is one of the following, it implicitly inserts a semicolon.

A symbol (foo, __bar) break continue fallthrough return
A string literal A character literal A boolean literal An integer literal A float literal
--- ? ) } ]

There are some rough cases that I have come across with some of the code I have written that make for a slightly rough transition, but largely I am enjoying writing Onyx without semicolons. I believe this will be the default in a future release.

Converting Old Code

If you have old Onyx code that you want to convert to the new syntax, you can use these two POSIX shell commands to convert all for loops and case statements. It is a good idea to make a backup of all Onyx files in your project before running these commands. I personal used these commands on all Onyx projects I am currently working on and they worked flawlessly, but your mileage may vary.

$ find -name '*.onyx' -exec sed -ri 's/(\s+)for([^a-zA-Z0-9_][^:]*)\s*:/\1for\2 in/g' {} \;
$ find -name '*.onyx' -exec sed -ri 's/(\s+)case\s*([^:]*)\s*:\s*\.([a-zA-Z0-9_]+)/\1case .\3 as \2/g' {} \;

There is not a conversion for interfaces, but those are much less common so they should not take too long to migrate.

OVM-WASM support on MacOS

Thanks to community contributions, Onyx's custom WebAssembly runtime called OVM-WASM now has support on MacOS. OVM-WASM was created to allow for debugging of Onyx programs, which is now possible on MacOS. Simply install the newest version of Onyx, and use the newest version of the Visual Studio Code extension for Onyx to enable debugging support.

Array Programming

Thanks to more community contributions, Onyx now has support for basic array programming. This means that small arrays of 4 elements or less have special operator overloads for +, -, and *, as well as special accessors for their elements.

To see how potentially useful this is, consider this code snippet.

// Vector2 is just an alias for an array of 2 integers
Vector2 :: [2] i32

main :: () {
    v: Vector2;
    v.x = 10; // Here you can use `.x` and `.y` to
    v.y = 20; // directly set the first and second elements

    w := v * 2;


Miscellaneous Improvements


Onyx now performs a simple tree-shaking algorithm to reduce the output binary size substantially. It does this by removing code and data that is proven to be impossible to reach. This was rather simple to do in the Onyx compiler, since there is no partial compilation. Everything that could end up in the binary must pass through all stages of the compiler.

There is one caveat to note though. In order to make this as effective as possible, the methods field in the Type_Info_Union and Type_Info_Struct structures is now left empty by default. This is because there are many cases where including it would mean that you could access a procedure dynamically through the type information. This hurt the performance of the tree-shaking algorithm and meant that very little was removed. To fix this, a flag was added to the compiler that you can pass if you want method information for your type. Simply pass --generate-method-info when running or building.

while defer

Another small syntax change that I am experimenting with is an alternative way to do bottom-test loops (do {} while (...) in C). The old-syntax was while #bottom_test condition { ... }, but in this version you can also use the following.

i := 10;
while defer i < 10 {

This code would print "10", because the actual condition (i < 10) is not checked until after the body of the loop, hence the defer keyword.


To update to the newest version of Onyx simply use the same install script found on the homepage. It will automatically detect your previous install and will override it with the new version.

$ sh <(curl -sSfL)

Full Changelog






© 2020-2024 Brendan Hansen