wa_embedder

View Source

A WebAssembly-to-BEAM compiler for the Erlang ecosystem, written in Erlang. It parses a .wasm binary (via wa_parser), translates each function to Erlang abstract format, and compiles and loads the result as a native BEAM module that you can call directly.

This is the Erlang package. Elixir projects can depend on it directly, or use the companion wa_embedder_ex package for an idiomatic Elixir API (WaEmbedder.compile/1..4 + WaEmbedder.ImportError).

Repository layout (monorepo)

Two hex packages live in this repository:

PathPackageToolRole
repo rootwa_embedderrebar3The compiler core (pure Erlang)
wa_embedder_ex/wa_embedder_exmixThin Elixir wrapper + the test suite
test_data/cmakeShared WAT/C .wasm fixtures

The dependency direction is one-way: wa_embedder_ex (Elixir) → wa_embedder (Erlang) → wa_parser (Erlang). The core has no Elixir dependency.

Installation (rebar3)

%% rebar.config
{deps, [{wa_embedder, "~> 0.1"}]}.

Usage

{module, Mod} = wa_embedder:compile("module.wasm"),
Result = Mod:some_exported_fun(Arg).

compile/1,2,3,4 compiles and loads the module and returns the code:load_binary/3 result ({module, ModuleName} on success). Modules with imports take an imports map resolving each WASM import to an Erlang target (MFA tuple, external fun, or closure); unsatisfiable imports raise erlang:error({import_error, Map}).

Development

A nix develop shell provides erlang, elixir, rebar3, and the fixture toolchain (cmake, ninja, wabt, binaryen). Local sibling dependencies are wired automatically on shell entry:

  • Core → parser: rebar3 has no native {path, ...} dep, so the shell hook creates a _checkouts/wa_parser symlink to the sibling ../wa_parser checkout (a rebar3 checkout takes precedence over the {wa_parser, "~> 0.1"} hex dep).
  • Wrapper → core: the shell sets WA_EMBEDDER_PATH=.. so wa_embedder_ex/mix.exs builds against the sibling Erlang core.

Build and test

# Erlang core (repo root)
rebar3 compile

# Elixir wrapper + full fixture suite (in wa_embedder_ex/)
cd wa_embedder_ex && mix test

The test suite lives in wa_embedder_ex/test/ and compiles the WAT/C fixtures under the repo-root test_data/ (built by CMake/Ninja before the suite runs).

Building the fixtures manually

cd test_data
cmake -B build -G Ninja
ninja -C build            # WAT fixtures (default); `ninja -C build c_fixtures` for the C chain

Packaging

Build the hex tarballs without the local dev overrides so the correct hex deps are recorded:

# Core: remove the dev checkout so {wa_parser, "~> 0.1"} is recorded
rm -rf _checkouts && rebar3 hex build

# Wrapper: unset WA_EMBEDDER_PATH so the {:wa_embedder, "~> 0.1"} hex dep is used
cd wa_embedder_ex && env -u WA_EMBEDDER_PATH mix hex.build

Publish order: publish wa_embedder (core) first, then wa_embedder_ex (the wrapper's hex dep on the core cannot resolve until the core is on hex).

License

Released into the public domain under the Unlicense.