Beta Release 0.1.7
This release of Onyx brings exciting and overdue features, including switch expressions, WASIX support and an overhauled networking layer.
Switch Expressions
Switch expressions allow you to write inline switch
statements that evaluate to values, removing
a common pattern that can be seen here:
x: u32;
switch value {
case .Case1 do x = 2;
case .Case2 do x = 3;
case .Case3 do x = 5;
case .Case4 do x = 7;
}
The above code can be rewritten like so:
// When `switch` appears in an expression, its cases must look like
// case X => value
//
x: u32 = switch value {
case .Case1 => 2;
case .Case2 => 3;
case .Case3 => 5;
case .Case4 => 7;
}
One caveat to this new feature is that it stole the syntax for capturing a value when switching over a tagged
union. To fix this, case
blocks that capture the union value were given a new syntax that looks like for
-loops.
x: ? i32 = .{ Some = 123 };
switch x {
// By value
case value: .Some {
printf("X has value {}\n", value);
}
// Or by pointer
case &value: .Some {
printf("X has value {}\n", *value);
}
}
Networking Overhaul
A majority of the work done in this release was refactoring the networking portion of the core libraries to operate at the platform layer. The platform layer is an abstraction layer that sits just above all of the interesting system level operations, like file-operations, threads, and now networking.
Before, all network code was not abstracted because the onyx
runtime was the only one that could
support networking, so it wasn't a high priority item to refactor. That has changed however, with Wasmer's
introduction of WASIX.
WASIX
WASIX is an extention of WASI, with inspiration from POSIX functions. It brings many useful things like networking,
TTY, futexes, better threads, and even setjmp
/longjmp
.
This version of Onyx enables networking, TTY control, and futexes when compiling to the wasi
runtime when runtime.vars.WASIX
is defined. You can easily do this by passing -DWASIX
on the command line or by adding this line of code to your file.
use runtime
#inject runtime.vars.WASIX :: true
DynCallback Integration
A long awaited feature when it comes to working with C libraries is the ability to pass an Onyx function to a C library as a callback.
This is a common pattern employed by many C libraries, so it would be very nice to support it. Thanks to dyncallback
,
this is possible and very easy.
The cbindgen
library now supports translating functions passed as arguments into the C bindings that wrap an Onyx function
in a native function using dyncallback
.
#foreign "libraryA" {
external_func :: (callback: (i32) -> void) -> void ---
}
main :: () {
external_func(x => {
println(x);
});
}
Note that while it should be possible to use this with other WebAssembly runtimes, Wasmer does not currently provide a couple of
crucial functions in their C api to make this work. So sadly, you must be using the ovmwasm
runtime to use this feature.
Full Changelog
Additions: - Support for WASIX, a new, extended standard to WASI, popularized by Wasmer. - Define `WASIX` in `runtime.vars` to enable it. (`-DWASIX` on the CLI) - Adds support for networking, futexes, and TTY control in WASI. - `switch` expressions. - `switch` can appear at the expression level, and uses `case X => value` to specify cases. - `cbindgen` now supports passing functions as arguments. - Internally uses dyncallback - Only for OVM-wasm and Linux, for now. - Scoped values in interfaces. `X :: ...` is allowed in an interface now. - `#inject` works on interfaces. - Polling to the `io.Stream` functionality. - Used to query when data is read/write-able from a stream, for supported streams. - `io.stream_poll` - `misc.any_unwrap` to unwrap an `any` containing an optional. - `json.decode_with_result` - `json.decode_into` - `slice.group_by` Removals: Changes: - Complete overhaul of networking in the core library. - Backwards compatiblity was not strictly maintained, but common functions did not change, like `socket_send` and `socket_recv`. - When debugging, `/ 0` or `% 0` will trigger an exception to debug the error. Bugfixes: - `alloc.atomic` package was broken when `sync` package was missing. - `X.foo` would not work if `X` was a pointer to a union. - Captures by pointer would break if the value was a primitive whose address wasn't taken anywhere else. - Symbol name reported by documentation generation was incorrect for some methods.