Grain

WebAssembly をネイティブターゲットとする関数型プログラミング言語。 既存言語を Wasm に移植するのではなく、最初から Wasm 専用として設計された点が特徴。Oscar Spencer と Philip Blair が開発、OSS (MIT)。

なぜ Grain が存在するか

多くの言語は「既存の言語 → Wasm バックエンド追加」というアプローチ(Rust, C++, Go など)。この場合 Wasm は二次ターゲットであり、言語設計自体は Wasm の制約を考慮していない。

Grain は逆方向:Wasm の実行モデルに合わせて言語を設計した。線形メモリ、関数テーブル、モジュール境界といった Wasm の構造を言語側から自然に活用できる。

言語の特徴

特徴内容
型システム静的型付け、Hindley-Milner ベースの型推論
パラダイム関数型主体(式ベース)、命令的スタイルも可
データ型代数的データ型(enum / record)、パターンマッチング
モジュールファイル = モジュール。from / use で import
GC独自 GC を Wasm 線形メモリ上で実行
コンパイラOCaml 実装 → Wasm バイナリを直接出力(LLVM 不使用)
拡張子.gr

コード例

// 再帰で階乗
let rec factorial = (n) => {
  if (n <= 1) 1
  else n * factorial(n - 1)
}

print(factorial(10))
// 代数的データ型とパターンマッチング
enum Shape {
  Circle(Number),
  Rectangle(Number, Number),
}

let area = (shape) => {
  match (shape) {
    Circle(r) => Float64.mul(3.14159, Float64.mul(r, r)),
    Rectangle(w, h) => Float64.mul(w, h),
  }
}
// モジュールシステム: provide で公開、from/use で取り込み
module Main

from "list" use List
from "option" use Option

provide let double = (xs) => {
  List.map((x) => x * 2, xs)
}

print(double([1, 2, 3])) // [2, 4, 6]

コンパイルパイプライン

flowchart LR
    Src[".gr ソース"] --> Parse["パース<br/>(OCaml)"]
    Parse --> Type["型チェック<br/>+ 推論"]
    Type --> IR["中間表現<br/>(Anf / Mashtree)"]
    IR --> Wasm[".wasm 出力"]
    Wasm --> Runtime["Grain Runtime<br/>(GC + stdlib)"]

LLVM を経由せず、独自の中間表現から直接 Wasm バイナリを生成する。コンパイラ自体は OCaml で書かれている。

メモリ管理

Grain は Wasm の線形メモリ上に独自の GC ランタイムを載せている。WasmGC (Wasm ネイティブの GC 提案) ではなく、従来のアプローチ。

flowchart TB
    subgraph wasm["Wasm 線形メモリ"]
        Stack["スタック領域"]
        Heap["ヒープ領域<br/>(Grain が管理)"]
        GC["GC ランタイム<br/>(Grain 同梱)"]
    end
    GC -->|"mark & sweep"| Heap

ツールチェイン

コマンド用途
grain compile file.gr.gr → .wasm コンパイル
grain run file.grコンパイル + 即実行
grain doc file.grドキュメント生成
grain format file.grコードフォーマッタ
grain lspLSP サーバ(エディタ補完・診断)

grain run は内部で Wasmtime を使って実行する。ブラウザ向けには .wasm を書き出して JavaScript から WebAssembly.instantiate で読み込む。

Wasm を一次ターゲットにした言語たち

言語パラダイムGCコンパイラ実装
Grain関数型自前 GC(線形メモリ)OCaml
AssemblyScriptTypeScript 風自前 GC(線形メモリ)TypeScript
Moonbit関数型 + OOPWasmGCRust
AlmideLLM 最適化なし(Rust 経由で所有権)Rust

Grain と Moonbit は同じ「Wasm ネイティブ関数型」だが、GC 戦略が異なる。Moonbit は WasmGC を採用し、Grain は自前 GC。WasmGC 対応ランタイム(V8, SpiderMonkey)では Moonbit が有利だが、WasmGC 非対応環境では Grain のアプローチが動く。

制限・課題

押さえどころ(カード化候補)

関連

Graph