Haxeの新バージョン3.2.0がリリースされてめでたいので、新機能を紹介していきます。
Pythonターゲットの追加
Haxeから出力できる言語に新たにPythonが加わりました。JavaScriptターゲットと同じように、1ファイルにまとめられて出力されます。
-python 出力ファイル名
のオプションで出力が可能です。例えば
class Main {
static function main() {
new Main();
}
var a = "world";
function new () {
trace("hello " + a);
}
}
これが以下のようにコンパイルされます。
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
定数畳み込みの強化、ローカルのデッドコード削除
Haxe3.2では実験的に新しい静的アナライザが導入されました。このアナライザは、-D analyzer
のコンパイラオプションをつけることで使用できます。
これを有効にすることで、いままでより強力な定数畳み込みやローカルのデッドコード削除がおこなわれます。
では、オプションの有無による出力の違いを見てみます
class Main {
static function main() {
var i = 10;
if (i < 5) {
trace(5);
} else {
trace(i * i);
}
}
}
これを-D 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
有りでコンパイルした場合
(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
メタデータの追加・機能改善
クラスフィールドでの@:nativeの使用
@:nativeは出力時に、Haxe内で使う名前とは別の名前をつけるためのメタデータで、いままでクラスなどの型の名前について使用が可能でした。
新しいバージョンでは、クラスのメンバ変数、関数についてもこの@:nativeで別名がつけられるようになりました。
class Main {
static function main() {
Piyo.piyo();
}
}
extern class Piyo {
@:native("$piyo")
static function piyo():Void;
}
コンパイルすると以下のように出力されます
(function (console) { "use strict";
var Main = function() { };
Main.main = function() {
Piyo.$piyo();
};
Main.main();
})(typeof console != "undefined" ? console : {log:function(){}});
出力言語側のライブラリで予約語とか$
とか使ってるとexternを書くときに困ることがあったのですが、これが改善されました
Issue : #1492
@:callable
関数呼び出し可能なabstractを定義します。詳しくはIssue参照。
(haxe.Constraints.Function用のメタデータっぽくて、それ以外の使いどころがあるかよくわからなかった)
Issue : #3218
externの機能強化
externのクラスは外部ライブラリの型情報を記述するのに使います。このexternクラス内のみで使える新しい型が2つ作成されました
haxe.extern.EitherType
EitherTypeはEitherType<A, B>
という書き方で、AまたはBのクラスというのを指定できるクラスです。TypeScriptで言うところのUnion Typesです。
例えば、EitherType<Int, String>
はIntとStringのどちらを代入してもよく、どちらへ代入してもよいです。
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
haxe.extern.Rest
可変長引数をあつかえます。
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
IDEのサポート機能の強化
HaxeはコンパイラがIDEでの入力補完のための機能を提供しています。
FlashDevelop、SublimeText、Atomなどではこの機能を使っており、そのおかげで複雑な構文やマクロを使った場合でも入力補完が効くようになっています。(今のところ、IntelliJ IDEAのHaxeプラグインはこの機能を使ってない。使う予定はあるらしい)
3.2では、このIDEの補助機能について次の3つの新機能入りました。
変数の宣言場所を検索
変数の宣言の位置を取得する機能が入りました
変数の使用状況の検索
変数の使用位置をリストとして取得する機能が入りました。この機能はIDEの検索機能や、リネーム機能に役立つはずです。
トップレベルの補完
今まで補完が効くのはhoge.|
のように.
を打った後だけで、ローカル変数の補完やthis.
を省略した時の補完は効かなかったのですが、.
を打った後以外でも補完が使えるようになりました。
Issue : #327
これらの機能が今すぐIDEで使えるわけでは無いですが、今後のIDEの機能の充実には期待できそうです。
64bit整数がclassからabstractに
今までclassだったInt64がabstractになりました。これにより、+
や-
などの演算子を使って演算を行うことが可能になります。また、計算の高速化も望めます。
import haxe.Int64;
class Main {
static function main() {
var i:Int64 = 2000000000;
trace(i * i); //4000000000000000000
}
}
Issue : #2617
マクロの機能の強化
haxe.macro.Contextや、haxe.macro.Compilerに新しい機能が追加されてました。
Context.getLocalTVar()
現在の文脈に存在するローカル変数の一覧を取得できるようになりました。
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
Context.getCallArguments()
@:genericBuildのクラスのコンストラクタ呼び出し時に使われた引数の型を取得できます。詳しく知りたいならテストコードが参考になります。
Context.getDefines()
マクロでコンパイル条件のフラグのリストを取得できるようになりました。
Issue : #3336
Context.storeTypedExpr(expr:Expr)
Issue : #3906
Compiler.addGlobalMetadata
すべての型やフィールドに対して一括でメタデータを追加することができます。フィルターをかけて対象をしぼることもできます。
Issue : #3129
HaxeでのXML処理の実装
XML関連の処理が各プラットフォームごとの実装だったのが、新しいHaxeの実装に統一されました。
Issue : #3752
パターンマッチでのgetterへのアクセス
パターンマッチ中で、プロパティのgetterにアクセスできるようになりました
Issue : #3088
最後に
ここで紹介したのは、Haxe3.2の主要な変更だけで、他にもバグ修正や各ターゲットごとの改善なども行われています。もっと詳しく知りたい方はCHANGES.txtを確認してください。
また、破壊的な変更については
https://github.com/HaxeFoundation/haxe/wiki/Breaking-changes-in-Haxe-3.2.0
で、確認できます。