65
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WASM にコンパイルする言語を作った話

Last updated at Posted at 2025-03-29

動機

Rustのwasm_bindgenは色々と制約が多いのが課題で、あまり好きではなかった。
wasm_bindgenは本当に屑で糞です。少しの事やるのに死ぬほど冗長なコードになる
かといってAssemblyScriptやEmscriptenは環境構築が面倒で使う気にはなりません。

ということで自分好みのWebアセンブリ向け言語を作り始めた。
プロジェクト名は「Mystia」と言います(特に深い意味は無い)。

特徴

そこそこ強力な型推論

コンパイル時に厳密に型チェックされ、基本的に注釈は全く無しでも動きます!

image.png

--summaryオプションで型推論の結果を表示できます。

Rust/OCamlライクな文法

というかデザインは完全に私の思想になっています。
関数定義と代入は明示的にletで行い、最後の式はreturn無しでも値を返します。

image.png

コンパイラ

LLVMは使わず、抽象構文木から直接WAT(WebAssembly Text Format)を生成します。
Rustで実装しましたが、いずれはセルフホスティングも出来るようにしたい。

image.png

コード量も割とコンパクトです。

image.png

他言語連携

JavaScriptとのFFI(Foreign Function Interface)も作りました。
型情報を元にWASMのメモリから値を読み込んでいます。

image.png

REPL

対話実行環境はNode製です

image.png

Playground

インストール/環境構築不要でブラウザ上で動かせます。
ぜひ試してみてください!

image.png

実用性

アプリもちゃんと書けます

image.png

type Elm = int;

load new_elm(tag: str, parent: Elm): Elm;
load upd_elm(id: Elm, prop: str, content: str): void;
load evt_elm(id: Elm, name: str, func: str): void;
load concat(a: str, b: str): str;
load to_str(n: num): str;

pub let model = @{
    title: "Counter App",
    count: 0,
    layout: @{
        panel: null
    }
};

let view() = {
    let formatted = "Number: " + (model.count as str);
    upd_elm(model.layout.panel, "innerHTML", formatted)
};

pub let inc_btn() = {
    let model.count + 1;
    view()
};

pub let inc_key(key_code: int) = {
    if key_code == 39 then {
        let model.count + 1
    } else if key_code == 37 then {
        let model.count - 1
    };
    view()
};

let app() = {
    let frame = new_elm("div", null);
    upd_elm(frame, "style", "margin: 100px");
    evt_elm(frame, "keydown", "inc_key");

    let title = new_elm("h1", frame);
    upd_elm(title, "innerHTML", model.title);

    let model.layout.panel = new_elm("p", frame);
    upd_elm(model.layout.panel, "style", "font-family: monospace");
    view();

    let btn = new_elm("button", frame);
    upd_elm(btn, "innerHTML", "Increment");
    upd_elm(btn, "className", "button");
    evt_elm(btn, "click", "inc_btn")
};

app();
model.title

目標

制約が少なく自由度の高いWASM向け言語の選択肢となる事を目指しています。
また、今年のU-22プログラミングコンテストに応募予定です。

最後までご覧頂きありがとうございました!

65
27
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
65
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?