Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compile erlang code loaded into a string?

I have a generated string that contains the code for an erlang module.

Is there a way to compile the generated module straight from the string?

Or is there a way to convert the string into the format needed for compile:forms/1?

Or will I have to save it to a temp file first and then compile it with compile:file/1?

Alternatively, I can add support to the compile module, but there must be a reason why the good people that write erlang haven't added it.

like image 259
monkey_p Avatar asked Jan 29 '10 08:01

monkey_p


People also ask

Which function is used to compile an Erlang file?

To print a complete list of the options to produce list files, type compile:options() at the Erlang shell prompt. The options are printed in the order that the passes are executed.

Is Erlang compiled or interpreted?

Normally Erlang code is compiled ahead of time into BEAM bytecode. Depending on whether Erlang was started in embedded or interactive mode, the modules are either loaded on startup, or dynamically as they are referenced. If you are building a release, you basically have to compile ahead of time.


1 Answers

You need to scan your string into tokens, and then parse the tokens into forms. Unfortunately it is only possible to parse one form at a time, so you will need to either cut your string, or your tokens at form boundaries. Here is a short example:

% create tokens from strings containing forms
> {ok, MTs, _} = erl_scan:string("-module(z).").
> {ok, ETs, _} = erl_scan:string("-export([f/0]).").
> {ok, FTs, _} = erl_scan:string("f() -> hello_world.").
% tokens to erl_parse trees
> {ok,MF} = erl_parse:parse_form(MTs).
> {ok,EF} = erl_parse:parse_form(ETs).
> {ok,FF} = erl_parse:parse_form(FTs).

% compile forms to binary
> {ok, z, Bin} = compile:forms([MF,EF,FF]).
{ok,z,<<70,79,82,49,0,0,1,164,66,69,65,77,65,116,111,109,0,0,0,...>>}

% load module from binary
> code:load_binary(z, "nofile", Bin).
{module,z}

% test
> z:f().
hello_world

Alternatively you can scan your string, and then cut the resulting token list at {dot, _} tokens apart.

like image 104
Zed Avatar answered Sep 23 '22 06:09

Zed