Haxe

Haxe（ヘックス、発音記号は /heks/）はオープンソースの高級プログラミング言語、もしくはそのコンパイラである。 言語としてのHaxeは静的型付きのオブジェクト指向言語であり、構文はActionScript 3および標準化が中止されたECMAScript 4に似ている。Adobe FlashやJava仮想マシンおよび独自のNekoやHashLinkで実行可能なバイトコードにコンパイルされるほか、JavaScript、ActionScript 3、C++、Cppia、C#、Java、PHP 7、Python 3、Luaへのソースコードの変換が可能であるため、主にマルチプラットフォーム開発を目的として使用される。また、FlashからHTML5への移行にも適する。 2012年4月に表記がhaXeからHaxeに変更された。 Haxeのコンパイラは、AVMやJava VM、そして独自の仮想マシンであるNeko及びHashLinkのバイトコードや、JavaScript、ActionScript 3、C++、Cppia、C#、Java、PHP、Python 3、Luaのソースコードを生成する。複数のプラットフォームに「コンパイルする」この戦略は、"Write once, run anywhere" の思想に基づいている。これにより、プログラマが目的のために最良のプラットフォームを選択できる。 Haxeでは、これらプラットフォームは「ターゲット」と呼ばれる。 haXe Betaより対応(2006年2月)。バイトコードへコンパイルされる。主な想定プラットフォームは、Adobe Flash、Adobe AIR。 2007年3月、AVM2へ対応した。 haXe Betaより対応(2006年2月)。バイトコードへコンパイルされる。 1.0より対応(2006年5月)。単一のソースファイルを出力する。主な想定プラットフォームは、ブラウザやNode.js、Electron。 Dynamic型によってJavaScriptのライブラリをそのまま利用できるほか、著名なライブラリであれば、Haxelibに公開されている(あるいは自分で定義した)externライブラリを使用することで、型安全性を保ったまま利用することができる。 Haxe 4.0現在、ECMAScript 5に準拠したコードへコンパイルされる。加えて、4.0以降ではECMA Script 6から追加されたクラス定義に対応した。 1.xより対応(2007年3月)。複数のソースファイルを出力する。主な想定プラットフォームは、Adobe FlashやAdobe AIR。 2.0.0より対応(2008年7月)。複数のソースファイルを出力する。 Haxe 3まではPHP 5.1.0に準拠したコードへコンパイルされていたが、Haxe 4以降ではPHP 7.0.0へ変更された。 2.4.0より対応(2009年7月)。複数のソースファイルを出力する。主な想定プラットフォームは、WindowsやmacOS、Linux、iOS、Android、Tizen、BlackBerry。 C++ターゲットを利用するには、Haxelibに公開されているhxcppライブラリのインストールが必要となる。また、独自のガベージコレクション機能を実装している。 2.10.0より対応(2012年4月)。複数のソースファイルを出力する。主な想定プラットフォームは、.NET FrameworkやMono、ASP.NET、Unity。 Haxelibに公開されているhxcsライブラリによって、.NET Framework 2.0及び4.0の標準ライブラリを利用できるようになる。.NET Frameworkのパスを指定すれば、任意のバージョンを利用することも可能。 2.10.0より対応(2012年4月)。複数のソースファイルを出力する。 Haxelibに公開されているhxjavaライブラリによって、Java 8の標準ライブラリを利用できるようになる。 3.2.0-rc.2より対応(2015年5月)。単一のソースファイルを出力する。 3.2.0-rc.2より対応(2015年5月)。単一のスクリプトファイルを出力する。 Cppiaは、外部のコンパイラを必要としない、Haxe上で完結するC++のスクリプト実行機能を提供する。Haxelibで公開されているhxcppライブラリを必要とする。 3.3.0-rc.1より対応。単一のソースファイルを出力する。 3.3.0-rc.1より対応。バイトコードへコンパイルされる。主な想定プラットフォームは、WindowsやmacOS、Linux、iOS、Android、Nintendo Switch、PlayStation 4。 4.0.0-rc.3より対応。バイトコードへコンパイルされる。 静的型付きのオブジェクト指向言語である。HaxeはActionScriptから派生した言語であるため、基本構文はActionScript3と共通する部分が多い。 HaxeはActionScript3が持つような以下の機能を持つ。 クラス、インタフェース プロパティ パッケージ、モジュール機構 アクセス修飾子（ただし、publicとprivateの2段階のみ） ローカル関数、第一級関数オブジェクト、クロージャ 各種演算子（算術、代入、論理、文字列、条件、ビット） リフレクション これらの機能は、クラスのようにActionScript3とよく似た構文で提供されるものもあるが、プロパティのようにActionScript3とは異なる文法で提供されるものもある。 構文が似ていても細かい挙動がActionScript3と異なるものも多い。以下にそのようなHaxeの挙動をいくつか挙げる。 if文、switch文、ブロックが式であり、値を返す。 ローカル変数、関数のスコープが異なる。 privateのアクセス修飾子の意味合いが、ActionScript3のprotectedに相当する。 演算子の優先順位が異なる。 % が * と / より優先度が高い。 |、&、^の優先度が同じ。 |、&、^が、==、!=より優先度が高い。 また、ActionScript3にはあるがHaxeには存在しない機能もある。以下にその例を挙げる。 for(初期化式; 継続条件式; 再初期化式){} のC言語形式のfor文 XMLのリテラル その他、以下のような独自の機能を持つ 型推論 型パラメータ（ジェネリクス） インライン関数 列挙型（一般化代数的データ型） 型エイリアス (typedef) パターンマッチング 構造的部分型付け 関数の部分適用 条件付きコンパイル 配列内包表記、辞書内包表記 文字列リテラル内での改行、文字列内の変数展開（ヒアドキュメント） 静的拡張 (Mixin) マクロ Haxeでは細かい型宣言が可能である。 function func1(threeDimensionalArray:Array<Array<Array<Int>>>, string:String, bool:Bool) { ... } // オプションのInt整数値を渡し、Intを返す function func2(?i:Int):Int { return 0; } // 引数のない関数をパラメータとして渡す function func3(f:Void -> Void) { f(); } // Intを渡しIntを返す関数をパラメータとして渡す function func4(f:Int -> Int) { var result = f(1); } // 任意型を取り、任意型を返す function func5(d:Dynamic):Dynamic { return d; } Haxeは静的型付き言語であるが、Dynamic型やuntypedを用いることで部分的に型チェックを無効化できる。逆にexternクラスによる型定義を行うことで、動的型のターゲットのライブラリに対して型チェックを有効にして連携できる。 列挙型 (enum) はHaxeの重要な特徴である。 Haxeの列挙型は他の多くの言語のように単に値を列挙して識別子をつけるものよりも抽象的で、列挙子（Haxeではenumコンストラクタと呼ぶ）ごとに異なるパラメータつことが可能である。このような列挙型はMLやHaskellのような言語の代数的データ型に相当する。 これにより、自身をパラメータにもって再帰構造をつくったり、木構造を作ったりできる。 以下の例のようにインスタンス化して使う。 enum Color { red; green; blue; rgb: (r:Int, g:Int, b:Int); } class Colors { static function toInt(c:Color):Int { return switch (c) { case red: 0xFF0000; case green: 0x00FF00; case blue: 0x0000FF; case rgb(r, g, b): (r << 16) | (g << 8) | b; } } static function validCalls() { var redint = toInt(Color.red); var rgbint = toInt(Color.rgb(100,100,100)); } } Haxeの標準ライブラリはすべてのターゲットで動作するもの、すべてでは無いが複数のターゲットで動作するもの、個別のターゲットのみで動作するものがある。以下にそれぞれの例をあげる。 すべてのターゲットで動作するもの バイナリ操作 ZIP圧縮、解凍 テンプレートエンジン JSONの書き出し、読み込み ユニットテスト Base64のエンコードとデコード 正規表現（ターゲットごとで細かい動作は異なる） すべてではないが複数のターゲットで動作するもの 標準入出力、標準エラー出力（Flash、JavaScript以外のターゲット） SQLを操作するライブラリ (Neko, C++, PHP) 個別のターゲットで動作するもの Flash、Java、C#、PHP、Pythonのそれぞれのターゲットの標準のAPI HTML5標準のAPIおよびjQueryのextern (JavaScript) AST（抽象構文木）やコンパイルのオプションの操作（マクロ環境のみで動作[要出典]） このように機能それぞれに合わせた抽象化が行われているため、複数のターゲットで動作するような書き方と、個別のターゲットに依存してそのターゲットの利点を生かすような書き方の両方ができる。 個別のターゲットのに依存する場合の例として、JavaScript出力におけるHTML5 Canvasの使用例を示す。 import js.Browser; import js.html.CanvasElement; class Main { static public function main() { var canvas:CanvasElement = cast Browser.document.getElementById("canvas"); var ctx = canvas.getContext2d(); ctx.fillStyle = "#F00"; ctx.fillRect(50, 50, 100, 100); } } HaxeではFlashターゲットの場合はFlashのAPIをそのまま使用できるが、他のターゲットについてもFlashに類似したオープンソースのAPI (OpenFL) が開発されている。 クロスプラットフォームのライブラリであるOpenFLを用いて画像を表示するプログラムを示す。同一コードがFlash、HTML5、Windows/Mac/Linux/iOS/Androidネイティブで実行可能である。描画には、FlashではDisplayObject、HTML5ではWebGLまたはCanvas、ネイティブ環境ではOpenGLが使用される。 import flash.display.Bitmap; import flash.display.Sprite; import flash.Lib; class Main extends Sprite { public function new() { super(); var image = new Bitmap(openfl.Assets.getBitmapData("img/sample.png")); addChild(image); } static public function main() { Lib.current.addChild(new Main()); } } HaxeのコンパイラはOCamlで実装されている。Haxeの利用者にはOCamlの知識は必要ない。 Haxeのコンパイラは複数のプラットフォームへのコンパイルの他に以下のような機能を持つ。 デッドコード削除 定数畳み込み リソースデータの埋め込み IDEに対してコンパイル・補完・リファクタリング機能を提供するサーバ機能 ドキュメント生成用のXml出力 SWC、SWFのライブラリの利用（Flash） 静的リンク・動的リンク SWC、SWFのライブラリからのexternの生成 SWCファイルの生成 ソースマップの生成（JavaScript） jarライブラリの利用（Java） dllライブラリの利用（C#） Haxeでのプログラミングには各種の統合開発環境 (IDE) およびエディタが利用できる。Haxeのコンパイラには、IDEに対してコンパイル・補完機能を提供するサーバ機能が備わっている。 FlashDevelop Visual Studio Code - プラグイン Sublime Text - Haxeバンドル Atom - atom-haxe Vim - Vaxe IntelliJ IDEA - 公式プラグイン FDT Flashコミュニティを出自とする言語のため、ゲームの用例が多い（言語上はそれに限定されない）。以下に代表的なものを挙げる。 Evoland - Haxe創始者（Nicolas Cannasse）ほかによるインディーRPG Papers, Please - 架空の共産国の入国審査官を疑似体験するゲーム。OpenFLを使用。Metacriticのメタスコア85を獲得。GDC 2014のIndependent Games Festivalにおいて最優秀賞を受賞。 OpenFL - Showcase - OpenFLを使用したゲームのショーケース Stencyl - 2Dゲームエディタ。OpenFLを使用。 TiVo - Android、iOS、デジタルビデオレコーダのアプリケーションに使用している。 開発当初から現在まで、Nicolas Cannasseがプロジェクトのリーダーを務める。ActionScriptの代替コンパイラとして開発されたため、Flashターゲットの用途が多かったものの、現在はプラットフォーム中立な言語環境となることを目指している。 2005年 10月 フランスのブラウザゲーム開発会社Motion Twin（英語版）の独自ActionScriptコンパイラMTASCの後継プロジェクトとしてHaxeが誕生（当初の綴りはhaXe） 2006年 5月 Haxe 1.0がリリース、JavaScriptターゲットに対応 2008年 7月 Haxe 2.0がリリース、Franco PonticelliによりPHPターゲットが追加 2009年 7月 Haxe 2.04がリリース、Hugh SandersonによりC++ターゲットが追加 2011年 JavaScriptターゲットのメンテナとして参加したBruno Garciaにより、2.08と2.09のリリースにおいてJavaScriptターゲットの最適化が行われた Simon Krajewskiがチームに参加 Cauê WaneckによりJavaおよびC#ターゲットが追加 2012年 4月 パリ開催のWorld Wide Haxeカンファレンスにおいて、表記をHaxeに変更すること、次のメジャーバージョンとなるHaxe 3に向けて破壊的変更を行うことがアナウンスされる Nicolas CannasseがMotion Twinより独立、インディーゲーム開発会社Shiro Games（英語版）およびHaxe Foundationを設立 2013年 5月 Haxe 3.0がリリース Haxeの名前は、短くシンプルで使われていないこと、また新しい技術を成功に導くために必要な X を中に持っていること（has a X inside）から命名された。 当初の綴りはhaXeであったが、2012年4月のWorld Wide Haxeカンファレンスにおいて、表記を固有名詞として馴染みやすいHaxeに変更することがアナウンスされた。 HaxeはJavaScript生成言語（いわゆる「altJS」）のひとつとしてしばしば言及される。比較対象となる主な言語として、以下が挙げられる。 CoffeeScript TypeScript Dart JSX HashLinkは、Nekoの後継とされる新しい仮想マシンで、2016年10月20日に開催された"London Haxe Meetup 20th October 2016"にて発表された。x86及びx86-64のWindows、macOS、Linux上で動作する。DirectXやSDL、OpenALをベースとしたマルチメディア機能のほか、zlibなどの著名なライブラリを内包する。またWindows限定ではあるが、一部のネイティブGUIコンポーネントも利用できる。なお、Neko VMとは異なり静的型付けである。実行にはHashLinkバイトコードファイル(拡張子は.hl)を用いる。 HashLinkの動作形態として、HL/JIT方式とHL/C方式の2種類がある。HL/JIT方式では、実行時コンパイラを通して仮想マシン上で動作させる為、コンパイル速度が高速でデバッグに向いている。一方、HL/C方式では仮想マシンは使用されず、代わりにC言語ソースコードを出力する。出力されたCソースコードは、任意のCコンパイラでビルドでき、より高いパフォーマンスと移植性が期待できる。例えば、iOSやAndroidなどのモバイルOS、PlayStation 4やNintendo Switchなどの家庭用ゲーム機といった、デスクトップ環境に限定されない様々なプラットフォームへの移植が比較的容易となる。実例として、このHashLinkとゲームエンジンであるHeapsで開発されているMotion Twin社のDead Cellsは、PlayStation 4、Nintendo Switch、Xbox One向けに移植されている。