Host Profiles
The toolchain supports two host profiles and an alternative compilation mode:
| Flag | Output | When to use |
|---|---|---|
--host wasi |
single .wasm |
WASI runtimes (wasmtime, etc.) — default |
--host browser |
.wasm + .js + .d.ts |
import from a web application |
--aot |
wasm without embedded VM | experimental ZoloIR→wasm backend |
--host browser mode generates JavaScript glue and TypeScript types alongside
the .wasm, letting you import the module directly in TS/JS. --aot mode
swaps the VM-embedded payload for the experimental native backend: supports
integer arithmetic, recursion, if/while, string literals, and print.
The following example demonstrates all three modes with a simple recursive fib
function, ideal for verifying that control-flow logic works correctly in each
profile:
fib(10) with the three modes: WASI, browser, and AOT.
// Feature: wasm host profiles & AOT — `--host` / `--aot`
// Syntax: `zolo build file.zolo --emit wasm --host wasi|browser [--aot]`
// When to use: target a WASI runtime vs the browser, or opt into the
// experimental ahead-of-time ZoloIR->wasm backend.
// Run:
// zolo build 32-webassembly/02-host-profiles.zolo --emit wasm --host wasi
// # -> 02-host-profiles-0.0.0.wasm (WASI host profile, the default)
//
// zolo build 32-webassembly/02-host-profiles.zolo --emit wasm --host browser
// # -> .wasm + .js + .d.ts (browser glue for import in a web app)
//
// zolo build 32-webassembly/02-host-profiles.zolo --emit wasm --aot --host browser
// # pure-wasm AOT (no embedded VM). Runs the supported subset: int math,
// # recursion, if/while, string literals, and print. Serve over http and
// # import the generated .js, or run with node:
// # node crates/zolo-wasm-aot/tests/run_wasm.mjs <file>.wasm -> fib(10) =\t55
//
// host=wasi -> a single .wasm wired for a WASI runtime (wasmtime, etc.)
// host=browser-> .wasm plus generated `.js` loader and `.d.ts` types so
// you can `import` it from TypeScript/JS.
// --aot -> swaps the VM-embedded payload for the experimental
// ZoloIR-native wasm backend.
fn fib(n: int) -> int {
if n < 2 { return n }
return fib(n - 1) + fib(n - 2)
}
print("fib(10) =", fib(10))
// expected (run natively): fib(10) = 55
Requires the Zolo CLI/host — open in the playground or run locally.
To explore the AOT performance ceiling, the fibonacci.zolo file pushes the
computation to Fibonacci of very large numbers via matrix exponentiation with
BigInt — and also uses std::os::clock() to measure time:
O(log n) Fibonacci with BigInt and timing; illustrates std::os as the only wasm-safe API.
// Feature: wasm host profiles & AOT — `--host` / `--aot`
// Syntax: `zolo build file.zolo --emit wasm --host wasi|browser [--aot]`
// When to use: target a WASI runtime vs the browser, or opt into the
// experimental ahead-of-time ZoloIR->wasm backend.
// Run:
// zolo build 32-webassembly/02-host-profiles.zolo --emit wasm --host wasi
// # -> 02-host-profiles-0.0.0.wasm (WASI host profile, the default)
//
// zolo build 32-webassembly/02-host-profiles.zolo --emit wasm --host browser
// # -> .wasm + .js + .d.ts (browser glue for import in a web app)
//
// zolo build 32-webassembly/02-host-profiles.zolo --emit wasm --aot --host browser
// # pure-wasm AOT (no embedded VM). Runs the supported subset: int math,
// # recursion, if/while, string literals, and print. Serve over http and
// # import the generated .js, or run with node:
// # node crates/zolo-wasm-aot/tests/run_wasm.mjs <file>.wasm -> fib(10) =\t55
//
// host=wasi -> a single .wasm wired for a WASI runtime (wasmtime, etc.)
// host=browser-> .wasm plus generated `.js` loader and `.d.ts` types so
// you can `import` it from TypeScript/JS.
// --aot -> swaps the VM-embedded payload for the experimental
// ZoloIR-native wasm backend.
// Fibonacci via matrix exponentiation (O(log n)) with BigInt
//
// Matrix [[a,b],[c,d]] stored as flat array [a, b, c, d]
// Multiply matrix a by matrix b, store result in a
fn mat_mul(a, b) {
let x = a[0] * b[0] + a[1] * b[2]
let y = a[0] * b[1] + a[1] * b[3]
let z = a[2] * b[0] + a[3] * b[2]
let w = a[2] * b[1] + a[3] * b[3]
a[0] = x
a[1] = y
a[2] = z
a[3] = w
}
// Square matrix a in-place
fn mat_square(a) {
let x = a[0] * a[0] + a[1] * a[2]
let y = a[0] * a[1] + a[1] * a[3]
let z = a[2] * a[0] + a[3] * a[2]
let w = a[2] * a[1] + a[3] * a[3]
a[0] = x
a[1] = y
a[2] = z
a[3] = w
}
// Raise matrix f to the power n using fast exponentiation
fn mat_power(f, n) {
if n <= 1 {
return
}
let one = 1n
let zero = 0n
let m = [one, one, one, zero]
mat_power(f, n ~/ 2)
mat_square(f)
if n % 2 != 0 {
mat_mul(f, m)
}
}
// Compute the n-th Fibonacci number using BigInt
fn fibonacci(n) {
if n == 0 {
return 0n
}
let one = 1n
let zero = 0n
let f = [one, one, one, zero]
mat_power(f, n - 1)
return f[0]
}
// --- Main ---
struct Console() {
fn new() {
Self { start: #{} }
}
fn time(self, name) {
self.start[name] = std::os::clock()
}
fn time_end(self, name) {
print("time = ", std::os::clock() - self.start[name])
}
}
fn main() {
let console = Console::new()
console.time("fibo")
300_000_000
|> fibonacci()
|> tostring()
|> .len()
|> |v| "len: {v}"
|> print()
console.time_end("fibo")
}
Requires the Zolo CLI/host — open in the playground or run locally.
Challenge
Compile 02-host-profiles.zolo with --host browser and inspect the three
generated files (.wasm, .js, .d.ts). What TypeScript signature is
generated for the fib function?
See also