formawasm

FormaLang in, WebAssembly components out.

formawasm takes a typed IrModule from FormaLang and emits a Component-Model .wasm binary — ready for wasmtime, wasmi, the browser, or any other compliant runtime. WIT comes for free from the public surface.

The pipeline

.fv source ──► FormaLang ──► IrModule ──► formawasm ──► .wasm component ──► your runtime

From source to component to run, no Rust needed

# Install the CLI…
cargo install formawasm

# …write a FormaLang source file…
echo 'pub fn id(x: I32) -> I32 { x }' > id.fv

# …compile it…
formawasm id.fv
# wrote id.wasm (… bytes) from id.fv

# …and run it under wasmtime.
wasmtime run --invoke 'id(42)' id.wasm
# 42
// id.wasm — auto-generated WIT view
package formawasm:generated;

world component {
  export id: func(x: s32) -> s32;
}

Or wire the backend into your build

// Cargo.toml
[dependencies]
formawasm = "0.0.1-beta"

// main.rs
use formalang::{Pipeline, compile_to_ir};
use formawasm::WasmBackend;

let module = compile_to_ir(source)?;
let bytes = Pipeline::new()
    .emit(module, &WasmBackend::new())?;
// bytes is a Vec<u8> ready for wasmtime, wasmi, jco, …

Why formawasm

Component Model native

Output is a Component-Model artifact from day one — never a bare core wasm module. Standards-compliant, runs in every compliant runtime, future-proof against the evolution of the platform.

WIT for free

The typed boundary is auto-generated from the public surface of each module. No hand-written .wit files, no manual interface bookkeeping. Mark a function pub; it becomes an export.

Runtime-agnostic

The backend stops at bytes. Pick wasmtime for the server, jco for the browser, wasmi for embedded — the same artifact runs unchanged. formawasm has no opinion on where you ship.

What's in the box

The full FormaLang surface

Structs, enums, traits, methods, generics (after monomorphisation), closures (after closure-conversion), virtual dispatch, host-provided externs. Strings, optionals, dictionaries, arrays, ranges — every container has a memory layout and a WIT mapping.

Optional optimization passes

Cargo features for binaryen (wasm-opt at -Os), DWARF debug sections, and a wasmparser defensive validation pass. All off by default; pay only for what you turn on.

Strict quality bar

Strict-clippy, typed errors via thiserror, no unwrap / panic in production paths. Tests return Result; every milestone runs end-to-end under wasmtime in CI.

Drop-in CLI

formawasm ships as a tiny single-file source-to-component driver — useful for smoke tests, quick experimentation, or as a build-pipeline step where wiring the Rust API isn't worth it.