Erlangでの「外出中」のコンパイル

場合によっては、アプリケーションの実行中にプログラムの特定の部分をコンパイルすると便利です。 たとえば、Javaの世界では、これがWebサーバーが.jspページをサーブレットにコンパイルする方法です。 このテクニックの他の可能なアプリケーションは、異なるテンプレート言語、正規表現などです。

Erlangでは、翻訳者はランタイムライブラリに組み込まれており、ブロードキャストのすべての段階を完全に制御できます。

方法


たとえば、1つの関数を含むモジュールを作成します。 それをさせてください-2つの数字の加算。

だから。 モジュールのテキストを含む行を作成します。

Src = [ "-module(testmodule).", "-export([add_two_numbers/2]).", "-compile(native)." , "add_two_numbers(X,Y) -> X+Y."]. 


次に、字句解析を行う必要があります。

  Lexems = lists:map(fun(X) -> {ok,Scanned,_} = erl_scan:string(X), Scanned end, Src). 


その結果、Lexemsのトークンのリストを取得します。

 [[{'-',1}, {atom,1,module}, {'(',1}, {atom,1,testmodule}, {')',1}, {dot,1}], [{'-',1}, {atom,1,export}, {'(',1}, {'[',1}, {atom,1,add_two_numbers}, ...  .. 


解析

  Parsed = lists:map(fun(X) -> {ok,P} = erl_parse:parse_form(X), P end, Lexems). 


この時点で、Parsedにはプログラムの内部表現が含まれます。 ところで、読みやすい形式で。

 [{attribute,1,module,testmodule}, {attribute,1,export,[{add_two_numbers,2}]}, {attribute,1,compile,native}, {function,1,add_two_numbers,2, [{clause,1, [{var,1,'X'},{var,1,'Y'}], [], [{op,1,'+',{var,1,'X'},{var,1,'Y'}}]}]}] 


そのため、いくつかの単純なケースでは、事前の字句解析および解析を行わずに、そのような属性ツリーを一度に構築することが妥当な場合があります。

ささいなままでした。 属性ツリーを仮想マシンのバイナリコードに変換し、

 {ok,_,B} = compile:forms(Parsed). 


そして、このコードをラインから仮想マシンにロードします。
 code:load_binary(testmodule,"nofile",B). 


チェックします
 19> testmodule:add_two_numbers(5,8). 13 


すべてが機能します! メモリ内にモジュールを作成し、翻訳し、ロードしましたが、今では他のアーランモジュールと変わりません。 どこからでも呼び出すことができ、変更できます(この機会にErlangに感謝します)。また、ネイティブオプションで、つまりhipeを使用してプロセッサコードにコンパイルしました。

Source: https://habr.com/ru/post/J129205/


All Articles