Skip to content

Commit 8b48fc8

Browse files
doc(moonbit): add MoonBit explanation
1 parent 0f147ae commit 8b48fc8

File tree

4 files changed

+361
-0
lines changed

4 files changed

+361
-0
lines changed

component-model/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
- [JavaScript](./language-support/javascript.md)
2424
- [Python](./language-support/python.md)
2525
- [Rust](./language-support/rust.md)
26+
- [MoonBit](./language-support/moonbit.md)
2627
- [WebAssembly Text Format (WAT)](./language-support/wat.md)
2728
- [Running Components](./running-components.md)
2829
- [Wasmtime](./running-components/wasmtime.md)

component-model/src/introduction.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This documentation is aimed at _users_ of the component model: developers of lib
1919
| [Worlds] | [JavaScript] | |
2020
| | [Python] | |
2121
| | [Rust] | |
22+
| | [MoonBit] | |
2223

2324
[Why Components?]: ./design/why-component-model.md
2425
[Components]: ./design/components.md
@@ -31,6 +32,7 @@ This documentation is aimed at _users_ of the component model: developers of lib
3132
[JavaScript]: ./language-support/javascript.md
3233
[Python]: ./language-support/python.md
3334
[Rust]: ./language-support/rust.md
35+
[MoonBit]: ./language-support/moonbit.md
3436

3537
[Composing]: ./composing-and-distributing/composing.md
3638
[Running]: ./running-components.md

component-model/src/language-support.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ without using a higher-level language front-end.
3737
- [Rust Tooling](./language-support/rust.md)
3838
- [Building a Component with `cargo component`](./language-support/rust.md#building-a-component-with-cargo-component)
3939
- [Running a Component from Rust Applications](./language-support/rust.md#running-a-component-from-rust-appliacations)
40+
- [MoonBit Tooling](./language-support/moonbit.md)
4041
- [WebAssembly Text Format (WAT)](./language-support/wat.md#wat-webassembly-text-format)
4142
- [Building a Component from WAT with `wasm-tools`](./language-support/wat.md#building-a-component-with-wasm-tools)
4243
- [Running a Component with Wasmtime](./language-support/wat.md#running-a-component-with-wasmtime)
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
# MoonBit Tooling
2+
3+
MoonBit is a programming language that provides first-class support for
4+
WebAssembly . This guide demonstrates how to build WebAssembly components using
5+
MoonBit, leveraging WIT (WebAssembly Interface Types) for interface definitions
6+
and the `wit-bindgen` toolchain for code generation.
7+
8+
This tutorial walks through building a component that implements the
9+
[`adder` world][adder-wit] defined in the `docs:adder` package. The component
10+
will export an `add` interface containing an `add` function that sums two
11+
numbers.
12+
13+
[adder-wit]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit
14+
15+
## 1. Install the Tools
16+
17+
### Installing MoonBit
18+
19+
First, install the MoonBit compiler and toolchain. Follow the installation
20+
instructions from the
21+
[MoonBit download page](https://www.moonbitlang.com/download).
22+
23+
Verify your MoonBit installation (below are the versions at the time of
24+
writing):
25+
26+
```
27+
$ moon version
28+
moon 0.1.20250801 (edae1ae 2025-08-01) ~/.moon/bin/moon
29+
moonc v0.6.24+012953835 ~/.moon/bin/moonc
30+
moonrun 0.1.20250801 (edae1ae 2025-08-01) ~/.moon/bin/moonrun
31+
```
32+
33+
### Installing `wit-bindgen`
34+
35+
Install the `wit-bindgen` CLI tool, which generates MoonBit bindings from WIT
36+
files:
37+
38+
```
39+
$ cargo install wit-bindgen-cli
40+
```
41+
42+
### Installing `wasm-tools`
43+
44+
Install `wasm-tools` for working with WebAssembly components:
45+
46+
```
47+
$ cargo install wasm-tools
48+
```
49+
50+
Verify the installations (below are the versions at the time of writing):
51+
52+
```
53+
$ wit-bindgen --version
54+
wit-bindgen-cli 0.44.0 (bdb4df54b 2025-08-14)
55+
$ wasm-tools --version
56+
wasm-tools 1.237.0
57+
```
58+
59+
## 2. Define the Interface (WIT)
60+
61+
Before generating the MoonBit project, you need to define the component
62+
interface using WIT. Create a directory for your project and define the WIT
63+
file:
64+
65+
```console
66+
$ mkdir moonbit-adder && cd moonbit-adder
67+
$ mkdir wit
68+
```
69+
70+
Create `wit/world.wit` with the following content:
71+
72+
```wit
73+
package docs:[email protected];
74+
75+
interface add {
76+
add: func(x: u32, y: u32) -> u32;
77+
}
78+
79+
world adder {
80+
export add;
81+
}
82+
```
83+
84+
This WIT definition:
85+
86+
- Declares a package `docs:adder` with version `0.1.0`
87+
- Defines an `add` interface with a single function that takes two `u32`
88+
parameters and returns a `u32`
89+
- Creates an `adder` world that exports the `add` interface
90+
91+
## 3. Generate MoonBit Project Structure
92+
93+
Use `wit-bindgen` to generate the MoonBit project structure and bindings:
94+
95+
```console
96+
$ wit-bindgen moonbit wit/world.wit --out-dir . \
97+
--derive-eq \
98+
--derive-show \
99+
--derive-error
100+
```
101+
102+
This command generates the following directory structure:
103+
104+
```
105+
.
106+
├── ffi
107+
│ ├── moon.pkg.json
108+
│ └── top.mbt
109+
├── gen
110+
│ ├── ffi.mbt
111+
│ ├── gen_interface_docs_adder_add_export.mbt
112+
│ ├── interface
113+
│ │ └── docs
114+
│ │ └── adder
115+
│ │ └── add
116+
│ │ ├── moon.pkg.json
117+
│ │ ├── stub.mbt
118+
│ │ └── top.mbt
119+
│ ├── moon.pkg.json
120+
│ ├── world
121+
│ │ └── adder
122+
│ │ ├── moon.pkg.json
123+
│ │ └── stub.mbt
124+
│ └── world_adder_export.mbt
125+
├── moon.mod.json
126+
├── wit
127+
│ └── world.wit
128+
└── world
129+
└── adder
130+
├── ffi_import.mbt
131+
├── import.mbt
132+
├── moon.pkg.json
133+
└── top.mbt
134+
```
135+
136+
The generated files include:
137+
138+
- `moon.mod.json`: MoonBit module configuration
139+
- `gen/`: Generated export bindings
140+
- `interface/`: Generated export interface bindings
141+
- `world/`: Generated export world bindings
142+
- `stub.mbt`: Main implementation file
143+
- `interface/`: Generated import interface bindings
144+
- `world/`: Generated import world bindings
145+
146+
## 4. Examine the Generated Code
147+
148+
The `wit-bindgen` tool generates MoonBit bindings that handle the WebAssembly
149+
component interface. Let's examine the generated
150+
`gen/interface/docs/adder/add/stub.mbt`:
151+
152+
```moonbit
153+
// Generated by `wit-bindgen` 0.44.0.
154+
155+
pub fn add(_x : UInt, _y : UInt) -> UInt {
156+
...
157+
}
158+
```
159+
160+
The `...` is the placeholder syntax in MoonBit. When executing
161+
`moon check --target wasm`, 'unfinished code' warnings will appear.
162+
163+
## 5. Implement the Component Logic
164+
165+
Now implement the `add` function in `src/lib.mbt`:
166+
167+
```moonbit
168+
// Generated by `wit-bindgen` 0.44.0.
169+
170+
///|
171+
pub fn add(x : UInt, y : UInt) -> UInt {
172+
x + y
173+
}
174+
```
175+
176+
## 6. Configure the Build
177+
178+
Ensure your `gen/moon.pkg.json` is properly configured for WebAssembly target:
179+
180+
```json
181+
{
182+
// link configuration for Wasm backend
183+
"link": {
184+
"wasm": {
185+
"exports": [
186+
// Export for cabi_realloc
187+
"cabi_realloc:cabi_realloc",
188+
// Export per the interface definition
189+
"wasmExportAdd:docs:adder/[email protected]#add"
190+
],
191+
"export-memory-name": "memory",
192+
"heap-start-address": 16
193+
}
194+
},
195+
"import": [
196+
{
197+
"path": "docs/adder/ffi",
198+
"alias": "ffi"
199+
},
200+
{
201+
"path": "docs/adder/gen/interface/docs/adder/add",
202+
"alias": "add"
203+
}
204+
]
205+
}
206+
```
207+
208+
## 7. Build the WebAssembly Component
209+
210+
Build the MoonBit code to WebAssembly:
211+
212+
```console
213+
$ moon build --target wasm
214+
```
215+
216+
This generates a WebAssembly module. To create a proper WebAssembly component,
217+
use `wasm-tools`:
218+
219+
```console
220+
$ wasm-tools component embed wit target/wasm/release/build/gen/gen.wasm \
221+
--encoding utf16 \
222+
--output adder.wasm
223+
$ wasm-tools component new adder.wasm --output adder.component.wasm
224+
```
225+
226+
You can verify the component's interface using `wasm-tools`:
227+
228+
```console
229+
$ wasm-tools component wit adder.component.wasm
230+
```
231+
232+
Expected output for both commands:
233+
234+
```wit
235+
package root:component;
236+
237+
world root {
238+
export docs:adder/[email protected];
239+
}
240+
package docs:[email protected] {
241+
interface add {
242+
add: func(x: u32, y: u32) -> u32;
243+
}
244+
}
245+
```
246+
247+
## 8. Testing the Component
248+
249+
### Using the Example Host
250+
251+
To test your component, use the [`example-host`][example-host] provided in this
252+
repository:
253+
254+
```console
255+
$ git clone https://github.com/bytecodealliance/component-docs.git
256+
$ cd component-docs/component-model/examples/example-host
257+
$ cp /path/to/adder.component.wasm .
258+
$ cargo run --release -- 5 3 adder.component.wasm
259+
```
260+
261+
Expected output:
262+
263+
```
264+
5 + 3 = 8
265+
```
266+
267+
[example-host]: https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/example-host/README.md
268+
269+
### Using Wasmtime
270+
271+
You can also test the component directly with `wasmtime`:
272+
273+
```console
274+
$ wasmtime run --invoke 'add(10, 20)' adder.component.wasm
275+
30
276+
```
277+
278+
## 9. Configurations
279+
280+
### --derive-eq --derive-show
281+
282+
These two options will add `derive(Eq)` and / or `derive(Show)` for all the
283+
generated types.
284+
285+
### --derive-error
286+
287+
This option will generate variants / enums whose names containing 'Error' as
288+
[suberrors](https://docs.moonbitlang.com/en/latest/language/error-handling.html#error-types).
289+
This allows you to integrate the MoonBit's error handling easier.
290+
291+
For example, for the following interface:
292+
293+
```wit
294+
package docs:[email protected];
295+
296+
interface add {
297+
record error {
298+
message : string
299+
}
300+
add: func(x: u32, y: u32) -> result<u32, error>;
301+
}
302+
303+
world adder {
304+
import add;
305+
}
306+
```
307+
308+
Will generate the following type:
309+
310+
```moonbit
311+
pub(all) suberror ComputationError {
312+
Overflow
313+
} derive(Show, Eq)
314+
```
315+
316+
and the following function:
317+
318+
```moonbit
319+
pub fn add(x : UInt, y : UInt) -> Result[UInt, ComputationError]
320+
```
321+
322+
which you may use it as:
323+
324+
```moonbit
325+
fn init {
326+
let a = add(1, 2).unwrap_or_error() catch { Overflow => ... }
327+
328+
}
329+
```
330+
331+
### --ignore-stub
332+
333+
It happens when you would like to regenerate the project due to the updated
334+
interface, but you don't want the `stub` file to be touched. You may use
335+
`--ignore-stub` option to avoid such modifications.
336+
337+
### --project-name
338+
339+
By default, the project name is generated per the name defined in the MoonBit
340+
file. You may use this option to specify the name of the project. It can also be
341+
used if you are generating the project as part of a larger project.
342+
343+
### --gen-dir
344+
345+
By default, the exportation parts are generated under `gen`. You may use this
346+
option to specify another directory.
347+
348+
## 10. References and Further Reading
349+
350+
- [MoonBit Official Website](https://www.moonbitlang.com/)
351+
- [MoonBit Language Documentation](https://docs.moonbitlang.com/)
352+
- [WebAssembly Component Model](https://component-model.bytecodealliance.org/)
353+
- [WIT Format Specification](https://component-model.bytecodealliance.org/design/wit.html)
354+
- [`wit-bindgen` Documentation](https://github.com/bytecodealliance/wit-bindgen)
355+
- [WebAssembly Tools](https://github.com/bytecodealliance/wasm-tools)
356+
- [Wasmtime Runtime](https://wasmtime.dev/)
357+
- [Component Model Examples](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples)

0 commit comments

Comments
 (0)