2007/06/11

Erlang 文字列をコンパイルする

文字列をコンパイルする方法です。

erl_scan:tokens で1文ずつスキャン。
erl_parse:parse_form で1文ずつパース。
compile:forms でモジュール単位でコンパイル。
code:load_binary でコンパイルしたものをロードです。

改行コードは \n にしておかないとだめです。


-module(compile_string).
-export([compile/1, test/0]).

compile(FormsStr) ->
Forms = mk_forms(lists:flatten(FormsStr)),
{ok, M, B} = compile:forms(Forms),
{module, M} = code:load_binary(M, atom_to_list(M), B),
M.

mk_forms(String) ->
mk_forms(String, []).

mk_forms([], Acc) ->
lists:reverse(Acc);
mk_forms(S, Acc) ->
{done, {ok, Tokens, _Line}, Rest} = erl_scan:tokens([], S, 0),
{ok, Parsed} = erl_parse:parse_form(Tokens),
mk_forms(Rest, [Parsed|Acc]).

test() ->
S = "-module(fib).
-export([fib/1]).
fib(1) -> 1;
fib(2) -> 1;
fib(N) -> fib(N-1) + fib(N-2).
",
compile(S),
fib:fib(10). % コンパイルした関数を呼出す。

もっと簡単な方法があるような気がします。
Common Lisp ならマクロでおしまいですね。
正規表現を入力にコンパイルされた関数を返す、なんて使い方をしようかと思っています。

0 件のコメント: