Erlang/OTP Forums

Author Message

<Erlang questions mailing list  ~  compiling a module from a string

uwiger
 Posted: Thu Jul 06, 2006 2:32 pm
User Joined: 03 Jul 2006 Posts: 604 Location: Sweden
 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: erlang-questions@erlang.org > 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 Post recived frommailinglist
axel
 Posted: Thu Jul 06, 2006 2:59 pm
User Joined: 03 Mar 2005 Posts: 271
 On 2006-07-06 16:19, Ulf Wiger (AL/EAB) wrote: >> 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. when faced with a similar problem for a pretty printer (epp_dodger wanting a file) i found that epp_dodger:parse/1 could handle an io object, instead of a file. so i wrote a string_io module that has open()/close() and received the io_requests. would this have worked for you? ie, can compile take an io object? bengt -- EPO guidelines 1978: "If the contribution to the known art resides solely in a computer program then the subject matter is not patentable in whatever manner it may be presented in the claims." Post recived frommailinglist
uwiger
 Posted: Thu Jul 06, 2006 8:40 pm
User Joined: 03 Jul 2006 Posts: 604 Location: Sweden
 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 Post recived frommailinglist
mats
 Posted: Mon Jul 10, 2006 11:03 am
User Joined: 28 Feb 2005 Posts: 168 Location: budapest,hungary
 Ulf Wiger (AL/EAB) wrote: > I want to effectively call > > Str = "-module(m).\n-export([foo/0]).\nfoo() -> foo.\n". > compile:string(Str, [binary]). this should work iff there are no #@#\$&* macros. if there is, it's pretty easy to write a subset of epp and call it between scanning and parsing. mats cl(Text) -> Forms = scan_and_parse(Text,1,[]), {ok,Mod,Bin} = compile:forms(Forms), code:load_binary(Mod,"generated",Bin). scan_and_parse([],_Line,Forms) -> lists:reverse(Forms); scan_and_parse(Text,Line,Forms) -> {done,{ok,Toks,NLine},Cont} = erl_scan:tokens([],Text,Line), {ok,Form} = erl_parse:parse_form(Toks), scan_and_parse(Cont,NLine,[Form|Forms]). Post recived frommailinglist
uwiger
 Posted: Mon Jul 10, 2006 11:32 am
User Joined: 03 Jul 2006 Posts: 604 Location: Sweden
 MaCro = Mats Cronqvist wrote: > > > > Str = "-module(m).\n-export([foo/0]).\nfoo() -> foo.\n". > > compile:string(Str, [binary]). > > this should work iff there are no #@#\$&* macros. if there > is, it's pretty easy to write a subset of epp and call it > between scanning and parsing. Well, my ram_file_io_server works like a charm and lets me use all the wonderful macros too. (: /U Post recived frommailinglist
mats
 Posted: Mon Jul 10, 2006 11:44 am
User Joined: 28 Feb 2005 Posts: 168 Location: budapest,hungary
 Ulf Wiger (AL/EAB) wrote: > > MaCro = Mats Cronqvist wrote: >>> Str = "-module(m).\n-export([foo/0]).\nfoo() -> foo.\n". >>> compile:string(Str, [binary]). >> this should work iff there are no #@#\$&* macros. if there >> is, it's pretty easy to write a subset of epp and call it >> between scanning and parsing. > > Well, my ram_file_io_server works like a charm and lets me > use all the wonderful macros too. (: > my post was mainly to inform the lurkers that it is not necessary to hack around in the kernel sources. of course, if i can save even one poor, unsuspecting soul from using macros i will surely get my reward in the hereafter. mats Post recived frommailinglist

Display posts from previous:

All times are GMT
Page 1 of 1