# wa_embedder

A WebAssembly-to-BEAM compiler for the Erlang ecosystem, written in Erlang. It
parses a `.wasm` binary (via [`wa_parser`](https://hex.pm/packages/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`](https://hex.pm/packages/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:

| Path              | Package          | Tool   | Role                                   |
|-------------------|------------------|--------|----------------------------------------|
| repo root         | `wa_embedder`    | rebar3 | The compiler core (pure Erlang)        |
| `wa_embedder_ex/` | `wa_embedder_ex` | mix    | Thin Elixir wrapper + the test suite   |
| `test_data/`      | —                | cmake  | Shared 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)

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

## Usage

```erlang
{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

```bash
# 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

```bash
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:

```bash
# 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](UNLICENSE).
