[erlang-questions] compile module from string, containing macro definitions
Chris Newcombe
chris.newcombe@REDACTED
Thu Mar 8 00:48:39 CET 2007
I'm using this code from Ulf Wiger to compile a module from a string:
http://www.erlang.org/ml-archive/erlang-questions/200607/msg00080.html
It is supposed to support epp-style macros.
However, when I test it with code containing a macro definition I get an error.
My compilation steps, test output and test code are all below.
e.g. This string compiles, loads, and executes correctly:
"-module(test_module).\n-export([test/1]).\ntest(P1) -> {test_result, P1}.\n"
But adding a single "-define(MY_MACRO, 1).\n" (which compiles fine
from a file)
"-module(test_module2).\n-export([test/1]).\n-define(MY_MACRO,
1).\ntest(P1) -> {test_result, P1}.\n",
… compile:forms/2 gives this error:
{error,
[{".",
[{none,
compile,
{crash,
lint_module,
{function_clause,
[{erl_lint,
function_state,
[{tree,
{".",attribute},
...
I've never used syntax_tools/epp_dodger or compile:forms before so any
help would be greatly appreciated!
Thanks,
Chris
> c("/home/cnewcom/backups/ram_file_io_server", [{outdir, "/home/cnewcom/backups/"}]).
{ok,ram_file_io_server}
> c("/home/cnewcom/backups/test_compile_string", [{outdir, "/home/cnewcom/backups/"}]).
{ok,test_compile_string}
> test_compile_string:test_no_macros().
{test_result,p1}
> test_compile_string:test_macros().
=ERROR REPORT==== 7-Mar-2007::15:29:25 ===
Error in process <0.60.0> with exit value:
{{nocatch,{compile_forms_error,{error,[{".",[{none,compile,{crash,lint_module,{function_clause,[{erl_lint,function_state,[{tree,{".",attribute},{attr,{".",3},[],none},{attribute,{".",{atom,3,define}},[{var,{".",3},'MY_MACRO'...
** exited: {{nocatch,
{compile_forms_error,
{error,
[{".",
[{none,
compile,
{crash,
lint_module,
{function_clause,
[{erl_lint,
function_state,
[{tree,
{".",attribute},
{attr,{...},...},
{attribute,...}},
{lint,function,test_module2,[],...}]},
{lists,foldl,3},
{erl_lint,forms,2},
{erl_lint,module,3},
{compile,lint_module,1},
{compile,'-internal_comp/4-anonymous-1-',2},
{compile,fold_comp,3},
{compile,internal_comp,...}]}}}]}],
[]}}},
[{test_compile_string,compile,3},
{erl_eval,do_apply,5},
{shell,exprs,6},
{shell,eval_loop,3}]} **
%% Test code
-module(test_compile_string).
-compile(export_all).
test_no_macros() ->
ModNameStr = "test_module",
Bin = compile(ModNameStr,
"-module(" ++ ModNameStr ++
").\n-export([test/1]).\ntest(P1) -> {test_result, P1}.\n",
[return_errors, return_warnings, verbose]),
{module, TestModuleNameAtom}
= code:load_binary(list_to_atom(ModNameStr), ModNameStr ++ ".erl", Bin),
{test_result, p1} = TestModuleNameAtom:test(p1).
test_macros() ->
ModNameStr = "test_module2",
_Bin = compile(ModNameStr,
"-module(" ++ ModNameStr ++
").\n-export([test/1]).\n-define(MY_MACRO, 1).\ntest(P1) ->
{test_result, P1}.\n",
[return_errors, return_warnings, verbose]).
compile(ModuleNameStr, CodeStr, CompileFormsOptions) ->
Filename = ModuleNameStr ++ ".erl",
{ok, Fd} = open_ram_file(Filename),
file:write(Fd, CodeStr),
file:position(Fd, 0),
case epp_dodger:parse(Fd) of
{ok, Tree} ->
Forms = revert_tree(Tree),
close_ram_file(Fd),
ModuleNameAtom = list_to_atom(ModuleNameStr),
%% note: 'binary' is forced as an implicit option, whether
it is provided or not.
case compile:forms(Forms, CompileFormsOptions) of
{ok, ModuleNameAtom, Binary} when is_binary(Binary) ->
Binary;
{ok, ModuleNameAtom, Binary, []} when
is_binary(Binary) -> % empty warnings list
Binary;
{ok, ModuleNameAtom, _, Warnings} ->
throw({compile_forms_warnings, Warnings});
Error ->
throw({compile_forms_error, Error})
end;
Error ->
close_ram_file(Fd),
throw({?MODULE, epp, Error})
end.
open_ram_file(Filename) ->
ram_file_io_server:start(self(), Filename, [read,write]).
close_ram_file(Fd) ->
file:close(Fd).
revert_tree(Tree) ->
[erl_syntax:revert(T) || T <- Tree].
More information about the erlang-questions
mailing list