search
LoginSignup
15

More than 5 years have passed since last update.

posted at

Haxe3.2の新機能まとめ

Haxeの新バージョン3.2.0がリリースされてめでたいので、新機能を紹介していきます。

Pythonターゲットの追加

Haxeから出力できる言語に新たにPythonが加わりました。JavaScriptターゲットと同じように、1ファイルにまとめられて出力されます。

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

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

    var a = "world";

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

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

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

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

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

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

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

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

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

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有りでコンパイルした場合

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

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

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

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

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

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

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

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

JavaScript出力
(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のどちらを代入してもよく、どちらへ代入してもよいです。

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

haxe.extern.Rest

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

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

IDEのサポート機能の強化

HaxeはコンパイラがIDEでの入力補完のための機能を提供しています。

FlashDevelopSublimeTextAtomなどではこの機能を使っており、そのおかげで複雑な構文やマクロを使った場合でも入力補完が効くようになっています。(今のところ、IntelliJ IDEAのHaxeプラグインはこの機能を使ってない。使う予定はあるらしい

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

変数の宣言場所を検索

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

変数の使用状況の検索

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

Issue : #569, #1807

トップレベルの補完

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

Issue : #327


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

64bit整数がclassからabstractに

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

Haxe
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のクラスのコンストラクタ呼び出し時に使われた引数の型を取得できます。詳しく知りたいならテストコードが参考になります。

Issue : #3183, #3833

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
で、確認できます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
15