compiling a module from a string

Ulf Wiger (AL/EAB) <>
Thu Jul 6 16:19:32 CEST 2006


 
So, I was able to hack my way in, in lieu of a documented solution:

1) Copy file_io_server.erl (from kernel) to ram_file_io_server.erl
   and modify slightly:

diff ram_file_io_server.erl file_io_server.erl
18c18
< -module(ram_file_io_server).
---
> -module(file_io_server).
27c27
< -define(PRIM_FILE, ram_file).
---
> -define(PRIM_FILE, prim_file).

2) Write the following code:

compile_string(_W, Mod, Str) ->
    Fname = Mod ++ ".erl",
    {ok, Fd} = open_ram_file(Fname),
    file:write(Fd, Str),
    file:position(Fd, 0),
    case epp_dodger:parse(Fd) of
	{ok, Tree} ->
	    Forms = revert_tree(Tree),
	    close_ram_file(Fd),
	    Forms;
	Error ->
	    close_ram_file(Fd),
	    Error
    end.

open_ram_file(Fname) ->
    ram_file_io_server:start(self(), Fname, [read,write]).

close_ram_file(Fd) ->
    file:close(Fd).

revert_tree(Tree) ->
    [erl_syntax:revert(T) || T <- Tree].


The 'ram' option to file:open/2 is not documented; the whole ram_file
framework seems to be secret. The problem with file:open(F, [ram, read,
write]) is that the opened file seems to get the same type of semantics
as with 'raw'. Epp_dodger uses the io module to parse the contents
behind Fd, and this doesn't work with raw devices.

(One could of course imagine a slight rewrite of file_io_server so that
it accepts some other low-level file driver other than prim_file... but
file_io_server is by all means undocumented too.)

After this, one just needs to call 

{ok,M,Bin} = compile:forms(Forms, [binary]),
compile:load_binary(M, F, Bin).

BR,
Ulf W

> -----Original Message-----
> From: Ulf Wiger (AL/EAB) 
> Sent: den 6 juli 2006 14:22
> To: 
> Subject: compiling a module from a string
> 
> 
> I want to effectively call
> 
> Str = "-module(m).\n-export([foo/0]).\nfoo() -> foo.\n".
> compile:string(Str, [binary]).
> 
> 
> Of course, this doesn't work, since compile.erl assumes that 
> the source has to come from a file. So does epp.erl, BTW, and 
> epp_dodger. 
> 
> A naive, but futile approach is of course:
> 
> {ok, Tokens, _} = erl_scan:string(Str),
> erl_parse:tokens(Tokens).
> 
> I'm sure there's a elegant sequence of commands that does 
> this, but which is it?
> 
> BR,
> Ulf W



More information about the erlang-questions mailing list