Examples
Complete examples demonstrating Wax features and their WebAssembly equivalents.
Arithmetic Functions
Wax
#[export = "add"]
fn add(x: i32, y: i32) -> i32 {
x + y
}
#[export = "multiply"]
fn multiply(x: i32, y: i32) -> i32 {
x * y
}
Equivalent WAT
(func $add (export "add") (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
i32.add)
(func $multiply (export "multiply") (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
i32.mul)
Factorial with Recursion
Wax
#[export = "factorial"]
fn factorial(n: i32) -> i32 {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
}
Equivalent WAT
(func $factorial (export "factorial") (param $n i32) (result i32)
local.get $n
i32.const 1
i32.le_s
if (result i32)
i32.const 1
else
local.get $n
local.get $n
i32.const 1
i32.sub
call $factorial
i32.mul
end)
Factorial with Tail Call
Wax
#[export = "factorial"]
fn factorial(n: i32) -> i32 {
become factorial_helper(n, 1)
}
fn factorial_helper(n: i32, acc: i32) -> i32 {
if n <= 1 {
acc
} else {
become factorial_helper(n - 1, n * acc)
}
}
Loop with Early Exit
Wax
#[export = "find_first_zero"]
fn find_first_zero(arr: &[i32]) -> i32 {
let i: i32;
let len: i32;
len = arr.length;
i = 0;
'search: loop {
if i >= len {
return -1
}
if arr[i] == 0 {
return i
}
i = i + 1;
br 'search;
}
}
Equivalent WAT
(func $find_first_zero (export "find_first_zero")
(param $arr (ref $array_i32)) (result i32)
(local $i i32)
(local $len i32)
local.get $arr
array.len
local.set $len
i32.const 0
local.set $i
(loop $search
local.get $i
local.get $len
i32.ge_s
if
i32.const -1
return
end
local.get $arr
local.get $i
array.get $array_i32
i32.eqz
if
local.get $i
return
end
local.get $i
i32.const 1
i32.add
local.set $i
br $search))
Structs and Methods
Wax
type point = { x: i32, y: i32 };
#[export = "make_point"]
fn make_point(x: i32, y: i32) -> &point {
{point| x: x, y: y}
}
#[export = "distance_squared"]
fn distance_squared(p1: &point, p2: &point) -> i32 {
let dx: i32;
let dy: i32;
dx = p1.x - p2.x;
dy = p1.y - p2.y;
dx * dx + dy * dy
}
Mutable Structs
Wax
type counter = { mut value: i32 };
#[export = "new_counter"]
fn new_counter() -> &counter {
{counter| value: 0}
}
#[export = "increment"]
fn increment(c: &counter) {
c.value = c.value + 1;
}
#[export = "get_value"]
fn get_value(c: &counter) -> i32 {
c.value
}
Arrays
Wax
type bytes = [mut i8];
#[export = "sum_bytes"]
fn sum_bytes(arr: &bytes) -> i32 {
let sum: i32;
let i: i32;
let len: i32;
sum = 0;
i = 0;
len = arr.length;
loop {
if i >= len {
return sum
}
sum = sum + arr[i] as i32_u;
i = i + 1;
br 'loop;
}
}
#[export = "fill_bytes"]
fn fill_bytes(arr: &bytes, val: i32) {
let i: i32;
let len: i32;
i = 0;
len = arr.length;
loop {
if i >= len {
return
}
arr[i] = val as i8;
i = i + 1;
br 'loop;
}
}
Exception Handling
Wax
tag divide_by_zero();
tag overflow();
#[export = "safe_divide"]
fn safe_divide(a: i32, b: i32) -> i32 {
if b == 0 {
throw divide_by_zero();
}
a /s b
}
#[export = "try_divide"]
fn try_divide(a: i32, b: i32) -> i32 {
'handler: do i32 {
try {
become safe_divide(a, b)
} catch [divide_by_zero -> 'handler]
unreachable
}
0 // Return 0 on division by zero
}
Recursive Types (Linked List)
Wax
rec {
type node = { value: i32, next: &?list };
type list = node;
}
#[export = "make_node"]
fn make_node(value: i32, next: &?list) -> &node {
{node| value: value, next: next}
}
#[export = "sum_list"]
fn sum_list(head: &?list) -> i32 {
if !head {
return 0
}
let n: &node;
n = head!;
n.value + sum_list(n.next)
}
Imports and Exports
Wax
// Import a function from the host environment
#[import = ("env", "log")]
fn log(value: i32);
// Import a global
#[import = ("env", "base_value")]
const base_value: i32;
// Export a function that uses the imports
#[export = "compute_and_log"]
fn compute_and_log(x: i32) -> i32 {
let result: i32;
result = x + base_value;
log(result);
result
}
Hash Function
A more complex example showing bitwise operations:
Wax
#[export = "hash_mix_int"]
fn hash_mix_int(h: i32, d: i32) -> i32 {
rotl(rotl(d * 0xcc9e2d51, 15) * 0x1b873593 ^ h, 13) * 5 + 0xe6546b64
}
#[export = "hash_finalize"]
fn hash_finalize(h: i32) -> i32 {
h = h ^ h >>u 16;
h = h * 0x85ebca6b;
h = h ^ h >>u 13;
h = h * 0xc2b2ae35;
h ^ h >>u 16
}