Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/aionescu/wasm-hs
Type-safe WebAssembly eDSL in Haskell
https://github.com/aionescu/wasm-hs
edsl haskell wasm web-assembly
Last synced: 20 days ago
JSON representation
Type-safe WebAssembly eDSL in Haskell
- Host: GitHub
- URL: https://github.com/aionescu/wasm-hs
- Owner: aionescu
- License: gpl-3.0
- Created: 2023-09-23T18:11:51.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-10-20T14:31:23.000Z (2 months ago)
- Last Synced: 2024-10-24T10:06:19.150Z (about 2 months ago)
- Topics: edsl, haskell, wasm, web-assembly
- Language: Haskell
- Homepage:
- Size: 123 KB
- Stars: 21
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
wasm-hs
This project provides an embedded domain-specific language (eDSL) for encoding WebAssembly in Haskell in a type-safe way (i.e. writing invalid Wasm results in a Haskell type error).
Below is a simple example of the DSL, a Wasm program that computes the factorial of 5:
```haskell
factorial :: WasmModule
factorial = wasm do
fn #factorial @'[Int] do
dup
const 1if gt then do
dup
const 1
sub
call #factorial
mul
else do
drop
const 1fn #main do
const 5
call #factorial
```## Supported features
* Arithmetic and comparison instructions
* Blocks and structured control-flow
* Local and global variables
* Type-safe dynamic memory access
* Functions, including mutual recursion## Ergonomics
To provide better ergonomics as a Haskell DSL, the project deviates from the WebAssembly specification in a few aspects:
* The operand stack can contain values of any Haskell type, not just the Wasm primitive types (`i32`, `i64`, `f32`, `f64`).
* Additional instructions are supported (`dup`, `swap`) that are not present in Wasm.
* Arithmetic and comparison instructions are overloaded using the standard Haskell typeclasses (`Num`, `Ord` etc.).
* Boolean instructions (comparisons, `br_if` etc.) use Haskell's native `Bool` type, rather than encoding booleans as `0` or `1` of type `i32`.
* Local variables are scoped explicitly (using a `let'` instruction), instead of being function-scoped.
* Memories are typed, and are scoped similarly to local variables (allocated with the `let_mem` instruction).## Interpreter
The project also includes an interpreter that uses continuation-passing style for efficient jumps, and local instances (via [`WithDict`](https://hackage.haskell.org/package/base/docs/GHC-Exts.html#t:WithDict)) for constant-time variable lookup.
Global variables and memories can be initialised with host-provided mutable references (`IORef`s), which allows the host to pass input data to the Wasm module, and inspect its mutations after execution.
## Limitations
* The DSL only allows the construction of self-contained Wasm modules (i.e. no external imports or exports).
* `call_indirect` and `br_table` are not supported.## Project structure
The main modules of the library are [`Language.Wasm.Instr`](src/Language/Wasm/Instr.hs), which defines the core `Instr` AST datatype and evaluation functions; and [`Language.Wasm.Module`](src/Language/Wasm/Module.hs), which builds upon `Instr` and defines a datatype for bundling definitions into modules, as well as module evaluation functions.
[`Language.Wasm.Syntax`](src/Language/Wasm/Syntax.hs) defines the DSL's syntactic sugar, and [`Language.Wasm.Prelude`](src/Language/Wasm/Prelude.hs) ties everything together into a single import.
The [`Language.Wasm.Examples`](src/Language/Wasm/Examples.hs) module defines a number of example Wasm programs, and [`Main`](app/Main.hs) contains the driver code.
## Dependencies
* GHC >=9.8.1
* Cabal >=3.10.2.0(Both can be installed via [GHCup](https://www.haskell.org/ghcup/))
## Building and running
The project has no external (non-Haskell) dependencies, and can simply be built using `cabal`:
```sh
cabal build
```Running the project with no arguments will run all the example programs:
```sh
cabal run
```If you want to run only specific examples, pass their names as arguments:
```sh
cabal run . -- factorial fibonacci
```If you specify an example multiple times, it will be executed that many times. This can be used to observe side-effects such as mutating memory shared by the host:
```sh
cabal run . -- squareAll squareAll
```## Running the tests
To run the library's test-suite, use the following command:
```sh
cabal run wasm-hs-test
```