🙆

Visula Studio Code WIT IDL plugin

2023/12/03に公開

TL;TR

  • WebAssembly Interface Typeで、Wasmコンポーネントのインタフェースを記述できます
  • Visual Studio Codeには WIT IDLプラグインがあります
  • WIT IDLプラグインは、シンタックスハイライトと、ある程度のコード補完ができます

背景:WebAssembly Interface Type (WIT)とは

WebAssembly(Wasm)周りのツールチェーンは、少しずつコンポーネントモデルに対応を始めています。
いくつかのWasmモジュールを組み合わせてもう少し粒度の大きいソフトウェアコンポーネントを定義するものがWasmコンポーネントです。

Wasmモジュールと同様、Wasmコンポーネントも他のプログラムに埋めこんで利用されます。他のプログラムから利用されるプログラムを書く場合、

  • ユーザー定義型を含めたインタフェースはどうなっているか
  • 文字列などをメモリー上にどのように表現するか
  • 関数や定数などのシンボルをどのように露出するか

といったことを取り決める必要があります。Wasmモジュールには上記のことに関する仕様はなく、開発者の努力によって解決されていました。例えばWasmモジュールのAPIレファレンスという形で取り決めを行う場合もあれば、言語ごとにSDKを提供することで解決を図る場合もありました。

Wasmコンポーネントでは、次の2つの仕様で開発者の努力を減らそうとしています:

WITはインターフェースを定義するための、インターフェース定義言語(InterfaceDefinition Language; IDL)を定義しています。WITで定義できるインターフェースには、以下のものを記述できます。

  • 露出する関数
  • 関数で利用するデータ型
  • 依存するコンポーネントのインターフェース

例えば分数を表す構造体と、それを扱う関数群を定義するインターフェースは次のように定義できます:

package component:fraction;

interface fraction {
    record fraction {
        denominator: u32,
        numerator: u32,
    }

    from-u32: func(value: u32) -> fraction;
    into-f32: func(value: fraction) -> float32;
    add: func(a: fraction, b: fraction) -> fraction;
    reduct: func(value: fraction) -> fraction;
}

world fraction-component {
    export fraction;
}

記述されたインターフェース定義から、Wasmコンポーネントのスケルトンコーや、コンポーネントを埋めこんで利用するホスト側のコードを生成できます。生成するツールには以下のものがあります。

WIT IDLプラグイン

WITで記述されたインターフェース定義は、.witという拡張子を持つことになっています。Visual Studio Codeには、witファイルを書くためのプラグインが存在します。それがWIT IDLプラグインです。

このプラグインはBytecode Allianceという、WasmコンポーネントやWASIの仕様策定を推進している団体が作成しているので、ほぼ「公式が提供するプラグイン」とみなせると思います。

このプラグインのできることは下記の2つです:

  • シンタックスハイライト
  • コード補完

どちらもWITの編集を大きく助けてくれます。特にWITに慣れていない時期には大きな助けとなります。私が個人的に助かった例を2つあげます。

例:使用できない文字の検出

WITで定義する関数や、データー構造につける名前で利用できる文字には制限があります。この制限はWasmコンポーネントモデルの仕様から来ています。具体的には次のように定められています:

label         ::= <word>
                | <label> '-' <word>
word          ::= [a-z] [0-9a-z]*
                | [A-Z] [0-9A-Z]*

私はRustに慣れていますので、つい癖で、語と語を_でつないでしまいます。

from_u32: func(value: u32) -> fraction;

このような文法ミスは、コード生成の時まで発見できませんでした。さいわいRust向けのコード生成器(wit-bindgen)は次のようにわかりやすいエラーメッセージを出すので、修正は難しくありません。ただ面倒なので、体験が良いかといえば、そうではありません。

/Users/chikoski/.cargo/bin/cargo component build
error: failed to create a target world for package `fraction` (/Users/chikoski/bbb/fraction/Cargo.toml)

Caused by:
    0: failed to parse local target from directory `/Users/chikoski/bbb/fraction/wit`
    1: invalid character in identifier '_'
            --> /Users/chikoski/bbb/fraction/wit/world.wit:9:5
             |
           9 |     from_u32: func(value: u32) -> fraction;
             |     ^

シンタックスハイライトによって、ミスに気づきやすくなっているのは助かります。

シンタックスハイライトで文法ミスが発見しやすくなっています。

例:プリミティブ型を正しく選べる

WITにはいくつかのプリミティブな型が定義されています。

ty ::= 'u8' | 'u16' | 'u32' | 'u64'
     | 's8' | 's16' | 's32' | 's64'
     | 'float32' | 'float64'
     | 'char'
     | 'bool'
     | 'string'
     | tuple
     | list
     | option
     | result
     | handle
     | id

私はよく次のようなタイプミスをしては、コード生成時に文法エラーを起こしていました:

  • 符号つき32ビット整数をs32ではなく、i32と書いてしまう
  • float32と書かなければならない、32ビットの浮動小数店をf32と書いてしまう

これらのエラーは、コード補完機能によって起きなくなりました。

コード補完で書き間違えが少なくなりました

プラグインのインストール方法

プラグインはVisual Studio Codeのマーケットプレースで公開されています。インストール方法はVisual Studio Codeのドキュメントで説明されています。そちらをご覧ください。

インストール時に、witファイルとの関連付けが自動的に行われます。witファイルをひらけば、自動的にWITIDLプラグインが動作します。

まとめ

WIT IDL以外にも、WITをサポートするプラグインはいくつか存在しています。それらの多くは、最新のWITの仕様に対応していないことが多いように感じています。そんななか、WIT IDLプラグインは最新の仕様にも追随しくことが期待されるので、私は最近このプラグインを使っています。

なお、開発はGitHubで行われています

Discussion