5

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.

monkey_p
  • 2,849
  • 2
  • 19
  • 16

2 Answers2

15

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.

Zed
  • 57,028
  • 9
  • 76
  • 100
  • 1
    Fixed the typo. I guess you could put your whole source code into a single string, scan it, and then cut the token list at each `{dot, _}`. – Zed Jan 29 '10 at 10:25
  • Also, note that includes do not work with this approach (see: http://stackoverflow.com/questions/2013119/compile-forms-with-included-header-files) – Zed Jan 29 '10 at 10:25
  • Exactly what I ended up doing, scanned for the {dot, _} :D – monkey_p Jan 29 '10 at 10:57
  • 1
    Unfortunately it is `erl_parse` which needs the spliting, `erl_scan:string` has no problems. I am working on a fix to yecc, which is used to generate `erl_parse`, so it can handle both to few and too many tokens in a sensible way. – rvirding Jan 29 '10 at 11:00
  • 2
    Use Aleppo if you need support for includes, ifdefs, and the gang: https://github.com/evanmiller/aleppo – Emiller Dec 15 '10 at 02:55
0

Store the content of the string in a file with a module name (if not there in the code) and compile it using compile module.
Code becomes available in the VM. I am using this technique to convert a configuration file into a module. This way there not much binary copy going on during the execution.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62