Visula Studio Code WIT IDL plugin
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コンポーネントのスケルトンコーや、コンポーネントを埋めこんで利用するホスト側のコードを生成できます。生成するツールには以下のものがあります。
- Rust: wit-bindgen
- JS: jco
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プラグインは最新の仕様にも追随しくことが期待されるので、私は最近このプラグインを使っています。
Discussion