はい、この記事は WebAssembly Advent Calendar 2017 22日目の記事です。

:bow: はじめに

この記事では、AssemblyScript (以降 AS) で i18n を実装したみた系の記事を書く予定でしたが間に合わなかったので、急遽、AS の次のバージョン v0.5.0 である AssemblyScript NEXT (以降 AS NEXT) で気になったことについて書きます。

AS について初めてな方は、@chikoskiさんが書いた WebAssembly Advent Calender 2017 のこの記事を読むと大体どんなことができるかどか分かると思うので、そちらを読んでください。

:warning: 注意事項

言うまでもないですが、AS NEXT はこの記事執筆時点でまだ開発中で、今後変わる可能性があります。

クラス、配列、文字列といった他の言語ではあって当たり前のような言語機能でさえ、まだ実装されていません。

適当に読み物的な感じで読んでもらえればと思います。

GitHub のリポジトリ

ここ最近、気づいた方がいるかと思いますが、AS をホストしているリポジトリが以下のように変わりました。

そうです。主が変わりました。

従来のホストしているリポジトリが prototype に変わりました。それに変わって、次のバージョンを開発していた next リポジトリが、主である assemblyscript に変わっています。

インストール方法

現時点で、開発版はまだ npm に公開されていません。なので、以下のように git clone してきてインストールする必要があります。

$ git clone https://github.com/AssemblyScript/assemblyscript.git assemblyscript
$ cd assemblyscript
$ npm install

WebAssembly と JavaScript との移植性

AS NEXT 以降では、WebAssembly (以降 WASM) なモノや JavaScript (以降 JS) なモノ両方に対応できる移植性のある開発ができるようになりそうです。

AS NEXT 以降では、以下のような、WASM 向けのみをターゲットとした assembly definitions と、WASM / JS 両方をターゲットした portable definitions という型定義が提供されるようです。

assembly definitions:

{
  "extends": "./node_modules/assemblyscript/std/assembly.json",
  "include": [
    "./**/*.ts"
  ]
}

portable definitions:

{
  "extends": "./node_modules/assemblyscript/std/portable.json",
  "include": [
    "./**/*.ts"
  ]
}

portable definitions を使えば、AS の コンパイラ asc と TypeScript (以降 TS) のコンパイラ tsc 両方で、WASM なモノや JS なモノに対応できるということになります。

これは、AS の作者 dcodeIO 氏が GitHub で言及しているように、まさに AS は TS のサブセットですね。

これをどうやって実現しているか気になる人は、portable definitions の型定義の中身や、JS のコードを見てみるといいでしょう。

移植可能なコーディングの書き方

AS NEXT 以降では上記で WASM と JS 両方、移植可能な実装が可能になると書きましたが、実装するに当たっていくつか考慮しないといけなことがあるようです。

明示的な変換

AS では、WASM の整数、実数、そして符号の有無などの型が仕様で定義されているものについては、型を独自に拡張して追加しています。ただ TS は JS のスーパーセットであるため、数値の場合は number という曖昧な型しかないため、明示的に型変換するような場合は以下のようなコーディングが必要になりそうです。

let someFloat: f32 = 1.5
let someInt: i32 = (<i32>someFloat) | 0

オーバーフロー

同様に、オーバーフローについても以下のようなコーディングが必要になりそうです。

let someU8: u8 = 255
let someOtherU8: u8 = (someU8 + 1) & 0xff

移植性のない演算

JS での数値は IEEE754 で規定されている倍精度型(double)であるため、64 ビットな数値を扱うことはできないため、portable definitions の型定義内(std/ portable.d.ts)では、i64u64 は使用していません。

AS ではこれに対処するために、以下な対処法を提供しているようです。

また、他に AS で load のようなビルドインで提供する関数の引数において、全ての値の範囲をサポートしていなかったり、String.fromCharCode のような複数の引数を指定可能な関数において、型が異なるものを指定できなかったりするようです。

ビルドイン関数

GitHub の AS NEXT の この wiki ページ の内容から、従来の AS (v0.3.0) で提供されているビルドインな関数が使える模様。

ただ、以下のような違いがあるようです。

  • 従来の AS v0.3.0 で提供されてた mallocfreeなどのような、C 言語ライクなメモリ操作系の関数は提供されていない (現時点でこのモジュールとリンクしていなようだ。)
  • 型変換関数が unsafe_castchange_type に変わった
  • assert 関数が入った (デバッグが便利になりそう)
  • parseIntparseFloatのような JS で提供される標準関数のようなものビルドインで提供

値の範囲

AS NEXT 以降では、整数、実数の扱い可能な値の範囲をグローバル定数で参照できるようです。

この wiki ページで表形式で確認できます。

開発状況とロードマップ

現状の開発状況としては、単純なモノであれば動作するようです。import/export、そしてビルドイン関数が動作し、関数も呼び出せるようです。基本的な動作の例として、ライフゲームが公開されています。

今後のロードマップは、wiki のロードマップと GitHub のこの Issue から以下のようです。

  • 実装された機能に対するテストケースの追加と問題の修正
  • 正規表現のリテラルのトークン化について検討
  • TODO:でマーキングしたものの対応
  • クラスについて検討 (GC の仕様が固まるまで待つ?)
  • TLSF メモリアロケーターの対応
  • 標準ライブラリstd/*.ts(Array/String/Map/Setなど)の実装 (メモリ周りとクラス周りが終われば進みそう)

まとめ

これまで、いろいろ AS NEXT について調べていろいろ書いてきました。WASM / JS 両方に対応可能になりそうなのはかなり面白いです。

WASM 周り、まだまだフロンティアですが、ひょっとしたら、将来 AS ベースで Web アプリケーションを実装する時代が来るのかもしれません。

おわりに

今年になって、メジャーブラウザでサポートしたため、WASM 大分盛り上がってきました。WASM の現時点での利用ユースケースとしては、ゲームや暗号処理などのスピードの高速化などがメインだと思います。

WASM は今後 GC やスレッドなど対応していくと思いますが、個人的には、ブラウザ以外で動作するよう進化してからが、本領発揮だと思っています。

WASM が Ruby、Python のような環境においても動作するようになれば、ライブラリとかクラスプラットフォーム対応とか容易にできるようなりますし。

自分の WASM に対するお気持ちはこんな感じです!

WASM の今後が楽しみです。 :grinning: