📜 ⬆️ ⬇️

On-the-fly Compilation in Erlang

In some cases it is convenient to compile certain parts of the program while the application is running. For example, in the world of Java this is how a web server compiles a .jsp page into servlets. Other possible uses of this technique are different pattern languages, regular expressions, etc.

In Erlang, the translator is built into the runtime library, and allows you to fully manage all stages of the broadcast.

How to do it

')
For example, create a module containing one function. Let it be - the addition of two numbers.

So. We form the line containing the text of the module.

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


Next we need to do a lexical analysis,

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


As a result, in Lexems we get a list of tokens, something like

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


Parsing

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


At this stage, Parsed will contain the internal presentation of our program. By the way, in a readable form.

 [{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'}}]}]}] 


So that in some simple cases it can be reasonable to build such an attribute tree right away without prior lexical and syntactic analysis.

There was a trifle. Convert an attribute tree to a virtual machine binary code,

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


And download this code from the string to the virtual machine.
 code:load_binary(testmodule,"nofile",B). 


Check
 19> testmodule:add_two_numbers(5,8). 13 


Everything is working! We formed a module in memory, read it, downloaded it, and now it is no different from other Erlang modules. You can call it from anywhere, change it (thanks to the Erlang for this opportunity), and, by the way, it was compiled with the native option — that is, into the processor code, using hipe.

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


All Articles