Skip to content

Emit Wasm

The --emit wasm flag tells the compiler to produce a .wasm module instead of a native binary. In the default mode (VM-embedded) the result is a single file that bundles the Zolo VM together with your bytecode; I/O capabilities are provided by the host-shim ABI — imported functions that the WASI runtime or JS loader inject at instantiation time.

The basic command:

zolo build 32-webassembly/01-emit-wasm.zolo --emit wasm
# -> target/01-emit-wasm-0.0.0.wasm

The simplest possible wasm program is a fn main() that calls print:

Minimal VM-embedded module; print is the only wasm-safe I/O today.

01-emit-wasm.zolo
// Feature: WebAssembly output — `zolo build --emit wasm`

// Syntax: `zolo build file.zolo --emit wasm`

// When to use: run Zolo inside a WASM host (WASI runtime, or a browser

//   via the generated JS glue).


// Run:

//   zolo build 32-webassembly/01-emit-wasm.zolo --emit wasm

//   # -> Built target/01-emit-wasm-0.0.0.wasm (...)

//

// By default this emits a VM-embedded module under the host-shim ABI:

// the Zolo VM + your bytecode are packaged into one `.wasm`, and host

// capabilities (I/O, etc.) are provided through imported shim functions.

// Default host profile is `wasi` (see 02 for `--host browser` / `--aot`).

//

// AOT (pure-wasm, no embedded VM) now executes this program end-to-end:

//   zolo build 32-webassembly/01-emit-wasm.zolo --emit wasm --aot --host browser -o target/aot/01.wasm

//   node crates/zolo-wasm-aot/tests/run_wasm.mjs target/aot/01.wasm

//     # -> Hello from WebAssembly!


fn main() {
  print("Hello from WebAssembly!")
}
// Heads-up (wasm-safe surface, current state): only `std::os` is

// wasm-safe today. crypto / log / datetime / fs / io still panic when

// called inside wasm, and `process.open()` panics at boot via

// `Instant::now()`. Keep wasm programs to plain compute + `print` for now.

//

// expected (run natively): Hello from WebAssembly!

Requires the Zolo CLI/host — open in the playground or run locally.

Current wasm-safe surface: only std::os works inside a wasm module. The crypto, log, datetime, fs, and io modules still panic when called, and process.open() panics at startup because it depends on Instant::now(). For now, keep wasm programs restricted to pure computation and print.

AOT mode also runs this program from start to finish:

zolo build 32-webassembly/01-emit-wasm.zolo --emit wasm --aot --host browser \
  -o target/aot/01.wasm
node crates/zolo-wasm-aot/tests/run_wasm.mjs target/aot/01.wasm
# -> Hello from WebAssembly!

Challenge

Add a second print call with the result of a simple arithmetic operation (e.g., 2 + 2) and recompile with --emit wasm. Confirm that the generated .wasm runs both lines in order.

See also

enespt-br