Haxe:ソースコードの変換

Haxeは非常に便利で実用的な言語ですが、小さなコミュニティであるため、ライブラリが少ないため、オープンソースライブラリをhaxeに統合するための「ヘッダーファイル」の準備に多くの時間を費やしています。 この言語と、以下の異なる言語でソースコードを変換する方法について少しお話ししたいと思います。



私は3年ほど前にhaxeプログラミング言語(彼の名前はhaXe)に精通し、それ以来私たちは別れませんでした。 なぜなら 有名な歌が言うように、この言語はHabréでまず最初にカバーされていません-haxeについては「簡単に言えば」です。



haxe in a nutshellについて



haxeに不慣れな人のために、少しの背景情報:



他の言語と同様に、haxeは特効薬ではありません。私には、2つの主要な領域が有用であると思われます。



コードを変換する



ある言語のソースコードを別の言語のコードに変換する方法は次のとおりです。

  1. 本格的な解析ツリーの構築(Abstract Source Tree = AST)
  2. ソースコードをより単純なもの(xmlなど)に変換できるツールを使用する。
  3. 正規表現の使用による「ブルートフォース」。


間違いなく、数学的に正しい方法が最初です。 すべてをきちんと行うことができ、理想的には、すぐに別の言語でコンパイルされたテキストを出力として取得できます。 短所-完全な分析は複雑で、詳細に敏感です。 コンパイラに関する文献で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を使用していなくても、少なくともプログラムのソースコードを処理する方法に興味を持っていただければ幸いです。 結局のところ、この単純な方法を使用すると、プログラムを言語から言語に変換するだけでなく、単にプログラムテキストを美しくする(美化する)ことができます。



All Articles