私は3年ほど前にhaxeプログラミング言語(彼の名前はhaXe)に精通し、それ以来私たちは別れませんでした。 なぜなら 有名な歌が言うように、この言語はHabréでまず最初にカバーされていません-haxeについては「簡単に言えば」です。
haxe in a nutshellについて
haxeに不慣れな人のために、少しの背景情報:
- この言語の構文は、ActionScriptをほぼ完全に繰り返します。ActionScriptはJavaScriptに似ていますが、データ型があります。
- ハードタイピング、ただし自動型推論(単純な場合);
- 緊密にバインドされたランタイムの欠如-コンパイラはhaxeコードを他の言語にのみ翻訳します(現在サポートされているのは、 neko 、php、javascript、flash / actionscript、c ++、java、c#; pythonも準備中です)。
- 非常に高速なコンパイラ。
他の言語と同様に、haxeは特効薬ではありません。私には、2つの主要な領域が有用であると思われます。
- マルチプラットフォームアプリケーションの作成(ここでは、 OpenFLゲームを開発するためのライブラリに言及する価値があります)。
- 複雑なjsアプリケーションを記述する(jsに直接記述するのは、入力ができないため問題があるため)。
コードを変換する
ある言語のソースコードを別の言語のコードに変換する方法は次のとおりです。
- 本格的な解析ツリーの構築(Abstract Source Tree = AST)
- ソースコードをより単純なもの(xmlなど)に変換できるツールを使用する。
- 正規表現の使用による「ブルートフォース」。
間違いなく、数学的に正しい方法が最初です。 すべてをきちんと行うことができ、理想的には、すぐに別の言語でコンパイルされたテキストを出力として取得できます。 短所-完全な分析は複雑で、詳細に敏感です。 コンパイラに関する文献でASTツリーの構築について読むことができます(たとえば、 Aho A.、Seti R.、Ulman J.、Lam M.-Compilers。原則、技術、ツールを参照)。
2番目の方法は、ソース言語に適したユーティリティがある場合にのみ可能です。 著者は、人気のイーゼル・ js jsライブラリーのhaxeラッパー・ジェネレーターを記述するときにyuidocを使用しました。後者は十分に文書化されているからです。
3番目の方法(正規表現処理を使用)は比較的簡単ですが、結果のコードの「ファイル調整」が必要です。 以下で説明するのは、このオプションについてです。
変換します!
私の意見では、正規表現には大きなプラスがあります-それらはすぐに書かれており、わずかなマイナスです:
- 原則として、ネストされた(繰り返しの)構造(任意のレベルのネストを持つ)を解析できません。
- 読みにくい(そして大きな式の場合-書くのも難しくない)。
最初の欠点は、実践が示しているように、特に本格的な変換を必要とせず、クラスとメソッドのヘッダーを「引き出す」だけでよい場合、ほとんどの言語にとってそれほど重要ではありません。 2つ目は、小さな正規表現を格納する定数を導入し、より複雑な構造を記述するために使用できるようにすることで、部分的に回避できます。
その結果、これらの同じルールには2つのタイプがある変換ルールのセットがあります。定数宣言と、検索/置換のための正規表現です。 c#からhaxeに変換するためのルールファイルのスニペットを次に示します。
ID = \b[_a-zA-Z][_a-zA-Z0-9]*\b LONGID = ID(?:[.]ID)* TYPE = LONGID(?:[<]\s*LONGID(?:\s*,\s*LONGID)*\s*[>])? // "int[]" => "Array<int>" /(TYPE)\s*\[\s*\]/Array<$1>/ // "int v" => "var v:int" /(TYPE)\s+(ID)/var $2:$1/
残っている唯一のことは、ソーステキストを含む入力ファイルと正規表現ルールのファイルを受け取り、これらのルールを適用した結果のファイルを出力するツールを作成することです。 そして、そのようなユーティリティが書かれました( リファクタリング )。 以下に、haxe言語の単純さと簡潔さを示す(希望する)コードを示します。
ルールを使用してファイルを読み取り、定数がどこにあり、どこが正規であるかを解析し、ソースファイルの後続の変換のために正規表現の配列を作成するクラスのコードを考えます。
import stdlib.Regex; // Regex stdlib, .. EReg import sys.io.File; // using static- StringTools ; // , String replace(); // StringTools.replace("abc", "b", "z"), using "abc".replace("b", "z"); // , - static using StringTools; class Rules { // (default, null) , , // (default), - (null); // "never" - , public var regexs(default, null) : Array<Regex>; public function new(rulesFile:String) { var text = File.getContent(rulesFile); // text regexs = []; var lines = text.replace("\r", "").split("\n"); // lines , var consts = new Array<{ name:String, value:String }>(); // // for haxe - foreach; // 0 9 : for (n in 0...10) for (line in lines) { line = line.trim(); if (line == "" || line.startsWith("//")) continue; var reConst = ~/^([_a-zA-Z][_a-zA-Z0-9]*)\s*[=]\s*(.+?)$/; // if (reConst.match(line)) { var value = reConst.matched(2); for (const in consts) { value = replaceWord(value, const.name, const.value); } consts.push({ name:reConst.matched(1), value:value }); } else { for (const in consts) { line = replaceWord(line, const.name, const.value); } regexs.push(new Regex(line.replace("\t", ""))); } } } // static function replaceWord(src:String, search:String, replacement:String) : String { var re = new EReg("(^|[^_a-zA-Z0-9])" + search + "($|[^_a-zA-Z0-9])", "g"); // map() src // , return re.map(src, function(re) { return re.matched(1) + replacement + re.matched(2); }); } }
おわりに
著者はWebアプリケーションを書くために3年間haxeを使用しています。 これは素晴らしいことです。クライアントとサーバーのコードを1つの言語で記述する機能+強い型指定+ jsに近い構文-これはすべて非常に楽しいことです。
作成されたリファクタリングツールは、haxeコードとサードパーティライブラリの統合を簡素化しました。 たとえば、最近、その支援により、 threejs jsライブラリのラッパーが作成されました。
haxeを使用していなくても、少なくともプログラムのソースコードを処理する方法に興味を持っていただければ幸いです。 結局のところ、この単純な方法を使用すると、プログラムを言語から言語に変換するだけでなく、単にプログラムテキストを美しくする(美化する)ことができます。