Haxe3.2の新機能まとめ


Haxeの新バージョン[3.2.0](http://haxe.org/download/version/3.2.0/)がリリースされてめでたいので、新機能を紹介していきます。

# Pythonターゲットの追加

[Haxeから出力できる言語](http://haxe.org/manual/introduction-what-is-haxe.html)に新たにPythonが加わりました。JavaScriptターゲットと同じように、1ファイルにまとめられて出力されます。

`-python 出力ファイル名`のオプションで出力が可能です。例えば

```hx:Haxe
class Main {
    static function main() {
        new Main();
	}

    var a = "world";

    function new () {
        trace("hello " + a);
    }
}
```

これが以下のようにコンパイルされます。

```py:Python
class Main:

	def __init__(self):
		self.a = None
		self.a = "world"
		print(str(("hello " + HxOverrides.stringOrNull(self.a))))

	@staticmethod
	def main():
		Main()



class HxOverrides:

	@staticmethod
	def stringOrNull(s):
		if (s is None):
			return "null"
		else:
			return s



Main.main()
```

Issue : [#2924](https://github.com/HaxeFoundation/haxe/pull/2924)

# 定数畳み込みの強化、ローカルのデッドコード削除

Haxe3.2では実験的に新しい静的アナライザが導入されました。このアナライザは、```-D analyzer```のコンパイラオプションをつけることで使用できます。

これを有効にすることで、いままでより強力な定数畳み込みやローカルのデッドコード削除がおこなわれます。

では、オプションの有無による出力の違いを見てみます

```hx:Haxe
class Main {
    static function main() {
        var i = 10;
        if (i < 5) {
            trace(5);
        } else {
            trace(i * i);
        }
	}
}
```

これを```-D analyzer```無しでコンパイルした場合

```js:JavaScript出力：analyzer無し
(function (console) { "use strict";
var Main = function() { };
Main.main = function() {
	var i = 10;
	if(i < 5) console.log(5); else console.log(i * i);
};
Main.main();
})(typeof console != "undefined" ? console : {log:function(){}});
```

```-D analyzer```有りでコンパイルした場合

```js:JavaScript出力：analyzer有り
(function (console) { "use strict";
var Main = function() { };
Main.main = function() {
	console.log(100);
};
Main.main();
})(typeof console != "undefined" ? console : {log:function(){}});
```

見ての通り、analyzerを有効にした場合では、結果がわかっているif文が消え去っていて、`i * i`もコンパイル時に計算されています。JavaScriptなどの特に動的言語のターゲットでは、このような事前計算は実行速度の向上につながります。

今のところ追加のコンパイルオプションが必要ですが、挙動が安定したらデフォルトで有効にすることを予定しているそうです。

また、このような定数畳み込みは現在のTypeScriptにはない機能なので、TypeScriptに対して優位なポイントにもなるのではないでしょうか。

Issue : [#3425](https://github.com/HaxeFoundation/haxe/pull/3425)

# メタデータの追加・機能改善

## クラスフィールドでの@:nativeの使用

@:nativeは出力時に、Haxe内で使う名前とは別の名前をつけるためのメタデータで、いままでクラスなどの型の名前について使用が可能でした。

新しいバージョンでは、クラスのメンバ変数、関数についてもこの@:nativeで別名がつけられるようになりました。

```hx:Haxe
class Main {
    static function main() {
        Piyo.piyo();
	}
}

extern class Piyo {
    @:native("$piyo")
    static function piyo():Void;
}
```

コンパイルすると以下のように出力されます

```js:JavaScript出力
(function (console) { "use strict";
var Main = function() { };
Main.main = function() {
	Piyo.$piyo();
};
Main.main();
})(typeof console != "undefined" ? console : {log:function(){}});
```

出力言語側のライブラリで予約語とか`$`とか使ってるとexternを書くときに困ることがあったのですが、これが改善されました

Issue : [#1492](https://github.com/HaxeFoundation/haxe/issues/1492)


## @:callable

関数呼び出し可能なabstractを定義します。詳しくはIssue参照。
（haxe.Constraints.Function用のメタデータっぽくて、それ以外の使いどころがあるかよくわからなかった）

Issue : [#3218](https://github.com/HaxeFoundation/haxe/issues/3218)


# externの機能強化

externのクラスは外部ライブラリの型情報を記述するのに使います。このexternクラス内のみで使える新しい型が2つ作成されました

## haxe.extern.EitherType
EitherTypeは`EitherType<A, B>`という書き方で、AまたはBのクラスというのを指定できるクラスです。TypeScriptで言うところのUnion Typesです。

例えば、`EitherType<Int, String>`はIntとStringのどちらを代入してもよく、どちらへ代入してもよいです。

```hx:Haxe
import haxe.extern.EitherType;

class Main {
    static function main() {
        Piyo.piyo(1);
        var result = Piyo.piyo("test");

        var i:Int = result;
        var str:String = result;
    }
}

extern class Piyo {
    static function piyo(i:EitherType<Int, String>):EitherType<Int, String>;
}
```

Issue : [#3465](https://github.com/HaxeFoundation/haxe/pull/3465)

## haxe.extern.Rest

可変長引数をあつかえます。

```hx:Haxe
import haxe.extern.Rest;

class Main {
    static function main() {
        Piyo.piyo(1);
        Piyo.piyo(1, 2);
    }
}

extern class Piyo {
    static function piyo(rest:Rest<Int>):Void;
}
```

Issue : [#3238](https://github.com/HaxeFoundation/haxe/issues/3238)

# IDEのサポート機能の強化

Haxeはコンパイラが[IDEでの入力補完のための機能](http://haxe.org/manual/cr-completion-overview.html)を提供しています。

[FlashDevelop](http://www.flashdevelop.org/)、[SublimeText](https://github.com/snowkit/sublime_haxe)、[Atom](https://github.com/snowkit/atom-haxe)などではこの機能を使っており、そのおかげで複雑な構文やマクロを使った場合でも入力補完が効くようになっています。（今のところ、IntelliJ IDEAのHaxeプラグインはこの機能を使ってない。[使う予定はあるらしい](https://github.com/TiVo/intellij-haxe/wiki/Roadmap--(Master-TODO))）

3.2では、このIDEの補助機能について次の3つの新機能入りました。

## 変数の宣言場所を検索

変数の宣言の位置を取得する機能が入りました

## 変数の使用状況の検索

変数の使用位置をリストとして取得する機能が入りました。この機能はIDEの検索機能や、リネーム機能に役立つはずです。

Issue : [#569](https://github.com/HaxeFoundation/haxe/issues/569),  [#1807](https://github.com/HaxeFoundation/haxe/issues/1807)

## トップレベルの補完

今まで補完が効くのは```hoge.|```のように```.```を打った後だけで、ローカル変数の補完や```this.```を省略した時の補完は効かなかったのですが、```.```を打った後以外でも補完が使えるようになりました。

Issue : [#327](https://github.com/HaxeFoundation/haxe/issues/327)

---

これらの機能が今すぐIDEで使えるわけでは無いですが、今後のIDEの機能の充実には期待できそうです。


# 64bit整数がclassからabstractに

今までclassだったInt64がabstractになりました。これにより、`＋`や`-`などの演算子を使って演算を行うことが可能になります。また、計算の高速化も望めます。

```hx:Haxe
import haxe.Int64;

class Main {
    static function main() {
        var i:Int64 = 2000000000;
        trace(i * i); //4000000000000000000
	}
}
```

Issue : [#2617](https://github.com/HaxeFoundation/haxe/pull/2617)

# マクロの機能の強化

[haxe.macro.Context](http://api.haxe.org/haxe/macro/Context.html)や、[haxe.macro.Compiler](http://api.haxe.org/haxe/macro/Compiler.html)に新しい機能が追加されてました。

## Context.getLocalTVar()

現在の文脈に存在するローカル変数の一覧を取得できるようになりました。

```hx
import haxe.macro.Context;

class Main {
    static function main() {
        var a = 0;
        test();
	}

    macro static function test() {
        var map = Context.getLocalTVars();

        trace(map["a"].t); // TAbstract(Int,[])
        trace(map["a"].id); // 7090

        return macro null;
    }
}
```

Issue : [#2783](https://github.com/HaxeFoundation/haxe/issues/2783)

## Context.getCallArguments()

[@:genericBuild](http://haxe.org/manual/macro-generic-build.html)のクラスのコンストラクタ呼び出し時に使われた引数の型を取得できます。詳しく知りたいなら[テストコード](https://github.com/HaxeFoundation/haxe/pull/3183/files)が参考になります。

Issue : [#3183](https://github.com/HaxeFoundation/haxe/pull/3183), [#3833](https://github.com/HaxeFoundation/haxe/issues/3833)

## Context.getDefines()

マクロでコンパイル条件のフラグのリストを取得できるようになりました。

Issue : [#3336](https://github.com/HaxeFoundation/haxe/pull/3336)

## Context.storeTypedExpr(expr:Expr)

Issue : [#3906](https://github.com/HaxeFoundation/haxe/issues/3906)

## Compiler.addGlobalMetadata

すべての型やフィールドに対して一括でメタデータを追加することができます。フィルターをかけて対象をしぼることもできます。

Issue : [#3129](https://github.com/HaxeFoundation/haxe/issues/3129)

# HaxeでのXML処理の実装

XML関連の処理が各プラットフォームごとの実装だったのが、新しいHaxeの実装に統一されました。

Issue : [#3752](https://github.com/HaxeFoundation/haxe/pull/3752)

# パターンマッチでのgetterへのアクセス

パターンマッチ中で、プロパティのgetterにアクセスできるようになりました

Issue : [#3088](https://github.com/HaxeFoundation/haxe/issues/3088)

# 最後に

ここで紹介したのは、Haxe3.2の主要な変更だけで、他にもバグ修正や各ターゲットごとの改善なども行われています。もっと詳しく知りたい方は[CHANGES.txt](https://github.com/HaxeFoundation/haxe/blob/development/extra/CHANGES.txt)を確認してください。

また、破壊的な変更については
https://github.com/HaxeFoundation/haxe/wiki/Breaking-changes-in-Haxe-3.2.0
で、確認できます。