SIMD.jsの型定義ファイルを作ってみた

[SIMD.js (ES.next stage3)](http://qiita.com/ConquestArrow/items/ce6c6ce3879d824d4fc5)の記事を書きつつ、実際に試してみるために欲しかったので[SIMD.jsのTypeScript用型定義ファイルを作ってみた](https://github.com/ConquestArrow/simd.d.ts)。


# 完成品(ver.0.9.1対応)

 * [github](https://github.com/ConquestArrow/simd.d.ts/blob/master/simd.d.ts)

# やったこと

 * [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) で探す
  * → ない。 [Issue](https://github.com/DefinitelyTyped/DefinitelyTyped/issues/5232)が立っていたが特に動きなし。 
 * ドキュメントを探す
  * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SIMD): 内容が古い。変更無いものは参考になる。
  * [SIMD型について](http://js-next.hatenablog.com/entry/2015/07/22/201208): 貴重な日本語資料。参考になる。 
  * [SIMD.js specification v0.9](http://tc39.github.io/ecmascript_simd/): 仕様書。正確だが、読みにくい。
 * [polyfill](https://github.com/tc39/ecmascript_simd/blob/master/src/ecmascript_simd.js)のコードを読む
  * 挙動の参考にはなったが、型情報という意味では普通のJSなのであまり。。。
 * polyfillを[dtsmake](https://github.com/ConquestArrow/dtsmake)に読ませてみる
  * 普通のライブラリと違うせいか、一部のメソッドのみしか出力されず
  * 内部で使っているTern.jsがちゃんと解析できてない
 * 手書きしてみる
  * ほとんど同じだけど引数の型が違うメソッドが、ある型にはあるけどこっちには無い、といったことがあり、早々にあきらめる
 * [生成用のコード](https://github.com/ConquestArrow/simd.d.ts/blob/master/src/SIMD.ts)を書く
  * polyfill&Node.jsを--harmony_simdで一部有効にした上で解析し、引数の型やJSDocコメントなどを一つ一つ手作業で出力するようにした
  * 仕様のver. UPにもすぐ対応できるように
  * ついでに簡易テストコードも生成

# 書き方でなやんだこと

 * `SIMD`オブジェクトは名前空間なので`namespace`で定義して悩まなかった
 * それぞれの型のコンストラクタは`new`できないのでinterfaceかfunctionかどちらで定義すべきか
 * SIMD型の固有メソッドはすべてstaticなので、namespace内で定義するかinterface内で定義するか
  * interfaceだとしたとき、interface名は`%SIMD%Constructor`？ `%SIMD%Static`?
 * 共通メソッドをまとめてinterfaceに定義して、各SIMD型のinterfaceで継承させる？させない？
 * 新しいプリミティブなデータ型をどう表現する？

## 最終的に

```ts

declare namespace SIMD{
	/**
	 * 128-bits divided into 4 lanes storing single precision floating point values.
	 */
	interface Float32x4{
		constructor: Float32x4Constructor;
		valueOf(): Float32x4;
		toLocaleString(): string;
		toString(): string;
		/**
		 * The initial value of the @@toStringTag property is the String value "SIMD.Float32x4".
		 */
		[Symbol.toStringTag]: string;
		[Symbol.toPrimitive](hint: "string"): string;
		[Symbol.toPrimitive](hint: "number"): number;
		[Symbol.toPrimitive](hint: "default"): Float32x4;
		[Symbol.toPrimitive](hint: string): any;
	}
	interface Float32x4Constructor{
		/**
		 * SIMD.Float32x4 constructor
		 * @param s0 A 32bit float specifying the value of the lane. 
		 * @param s1 A 32bit float specifying the value of the lane. 
		 * @param s2 A 32bit float specifying the value of the lane. 
		 * @param s3 A 32bit float specifying the value of the lane. 
		 * @return SIMD.Float32x4 object 
		 */
		(s0?: number, s1?: number, s2?: number, s3?: number): Float32x4;

		prototype: Float32x4;
//...(中略)
	}
	var Float32x4: Float32x4Constructor;
//...(略)
}

```

色々試行錯誤したが最終的には上記の方式に落ち着いている。lib.d.tsなど公式の組み込みオブジェクトで使われている方法に近い。

## 宿題１：プリミティブデータ型の表現

SIMD型は新しいデータ型なので、`Number`に対する`number`, `String`に対する`string`のように本来はTypeScriptの本体側がプリミティブデータ型として認識できなければいけない。厳密にいえば、例えば `SIMD.Float32x4` の コンストラクタで返す型は ラッパーの `Float32x4`ではなくて "float32x4"であるべきなのかもしれない。だが、普通の型定義ファイルの中でそういうものが定義できるのかわからない＆やってよいのか分からないのでラッパーinterfaceだけの定義にとどめた。

## 宿題２：DefinitelyTypedへプルリク

 * JSDocが不十分。基本MDNからの引用なのでライセンス上の問題なくするなら書き換えないといけない？
 * 標準APIだからlib.d.tsとかにマージすべき？
 * まだstage3。stage4になるまで待つべき？