diff --git a/apps/htoad/rebar.config b/apps/htoad/rebar.config index 012f24b..2cab891 100644 --- a/apps/htoad/rebar.config +++ b/apps/htoad/rebar.config @@ -6,7 +6,8 @@ {getopt, ".*", {git, "https://github.com/jcomellas/getopt.git", {branch, "master"}}}, {dynamic_compile, ".*", {git, "https://github.com/spawngrid/dynamic_compile", {branch, "master"}}}, {erlydtl, ".*", {git, "https://github.com/evanmiller/erlydtl.git", {branch, "master"}}}, - {parse_trans, ".*", {git, "https://github.com/esl/parse_trans.git", {branch, "master"}}} + {parse_trans, ".*", {git, "https://github.com/esl/parse_trans.git", {branch, "master"}}}, + {elixir, ".*", {git, "https://github.com/josevalim/elixir.git", {branch, "master"}}} ] }. {erl_opts, [nowarn_unused_record]}. diff --git a/apps/htoad/src/htoad.app.src b/apps/htoad/src/htoad.app.src index c6c57bd..c5e0e5a 100644 --- a/apps/htoad/src/htoad.app.src +++ b/apps/htoad/src/htoad.app.src @@ -14,7 +14,8 @@ dynamic_compile, erlydtl, parse_trans, - syntax_tools + syntax_tools, + elixir ]}, {mod, { htoad_app, []}}, {env, [ diff --git a/apps/htoad/src/htoad_toadie_server.erl b/apps/htoad/src/htoad_toadie_server.erl index 613ca94..32ba1e6 100644 --- a/apps/htoad/src/htoad_toadie_server.erl +++ b/apps/htoad/src/htoad_toadie_server.erl @@ -4,6 +4,8 @@ -include_lib("htoad/include/htoad.hrl"). -include_lib("htoad/include/stdlib.hrl"). +-include_lib("elixir/include/elixir.hrl"). + %% API -export([start_link/1]). @@ -96,7 +98,6 @@ handle_cast(apply, #state{ file = File, toadie = Toadie, applied = false } = Sta handle_cast(init, #state{ file = File } = State) -> try load_file(File) of {Toadie, Bin} -> - load_file(File), htoad:assert(#'htoad.toadie'{ filename = File, module = Toadie, server = self() }), lager:debug("Loaded toadie ~s", [File]), load_rules(File, Toadie, Bin), @@ -159,6 +160,19 @@ code_change(_OldVsn, State, _Extra) -> %% Private load_file(File) -> + case filename:extension(File) of + ".htd" -> + load_erl_file(File); + ".erl" -> + load_erl_file(File); + ".ex" -> + load_elixir_file(File); + ".exs" -> + load_elixir_file(File) + end. + + +load_erl_file(File) -> {ok, B} = file:read_file(File), S = binary_to_list(B), Module = list_to_atom(re:replace(File,"\\.","_",[{return, list}, global])), @@ -181,6 +195,22 @@ load_file(File) -> code:load_binary(Module, htoad_utils:file(File ++ ".beam"), Binary), {Module, Binary}. +load_elixir_file(File) -> + ModuleName = lists:flatten(io_lib:format("Elixir_Toadie_~w",[erlang:phash2(now())])), + {ok, B} = file:read_file(File), + Src = "defmodule " ++ ModuleName ++ " do\n" + "import Erlang.htoad_utils\n" + "Module.add_attribute __MODULE__, :htoad_absname, '" ++ File ++ "'\n" + "@compile {:parse_transform, :htoad_transform}\n" + ++ binary_to_list(B) ++ + "end\n", + Forms = elixir_translator:forms(Src, 1, File), + put(elixir_compiled, []), + elixir_compiler:eval_forms(Forms, 1, list_to_atom(ModuleName), #elixir_scope{ filename = File }), + [{Module, Binary}] = get(elixir_compiled), + erase(elixir_compiled), + {Module, Binary}. + load_rules(File, Toadie, Bin) -> case proplists:get_value(rules, Toadie:module_info(attributes)) of undefined -> diff --git a/apps/htoad/src/htoad_transform.erl b/apps/htoad/src/htoad_transform.erl index 201bd5f..660db16 100644 --- a/apps/htoad/src/htoad_transform.erl +++ b/apps/htoad/src/htoad_transform.erl @@ -79,20 +79,19 @@ do_transform(clause, {clause, Line, Head, G, B}, Context, {B1, Rec, State2} = transform(fun do_transform/4, State1, B, Context), {{clause, Line, Head1, G, B1}, Rec, State2}; +do_transform(application,{call, Line, {remote, RL, {atom, RL1, htoad_utils},{atom, RL2, F}}, [File]}, _Context, + #state{ absname = AbsName } = State) when F == load; F == file -> + {{call, Line, {remote, RL, {atom, RL1, htoad_utils}, {atom, RL2, F}}, + [ + filename_join(Line, File, AbsName) + ]}, true, State}; + + do_transform(application,{call, Line, {atom, Line1, F}, [File]}, _Context, #state{ absname = AbsName } = State) when F == load; F == file -> {{call, Line, {atom, Line1, F}, [ - {call, Line, {remote, Line, - {atom, Line, filename}, - {atom, Line, join}}, - [list_to_cons([ - {call, Line, {remote, Line, - {atom, Line, filename}, - {atom, Line, dirname}}, - [{string, Line, AbsName}]}, - File - ], Line)]} - ]}, true, State}; + filename_join(Line, File, AbsName) + ]}, true, State}; do_transform(_Type, Form, _Context, State) -> @@ -111,6 +110,19 @@ clause_scanner(_Type, Form, _Context, State) -> {Form, false, State}. +filename_join(Line, File, AbsName) -> + {call, Line, {remote, Line, + {atom, Line, filename}, + {atom, Line, join}}, + [list_to_cons([ + {call, Line, {remote, Line, + {atom, Line, filename}, + {atom, Line, dirname}}, + [{string, Line, AbsName}]}, + File + ], Line)]}. + + scan_file_record(Fields) -> DefaultFile = #file{}, RFields = record_info(fields, file), diff --git a/examples/simple.ex b/examples/simple.ex new file mode 100644 index 0000000..d79bf6e --- /dev/null +++ b/examples/simple.ex @@ -0,0 +1,17 @@ +def build_server do + file = {:file, dir, Erlang.filename.join('/tmp/srv','build_dir'), :undefined, :undefined, :undefined, ""}, + [ + ensure(:present, file), + on([ {:operating_system_name, :darwin}, + {:package_manager, :brew} ], + ensure(:present, {:package, 'git', :undefined})) + ] +end + +def main do + [ + load('base.htd') + on({:host, 'spawn.local'}, {:role, :build_server}), + on({:role, :build_server}, build_server) + ] +end diff --git a/rebar.config b/rebar.config index 7f77849..7424f27 100644 --- a/rebar.config +++ b/rebar.config @@ -1 +1,2 @@ {sub_dirs, ["apps/htoad","rel"]}. +{post_hooks, [{compile, "cp deps/elixir/exbin/*.beam deps/elixir/ebin/"}]}. diff --git a/rel/reltool.config b/rel/reltool.config index 10d79ad..c3768c8 100644 --- a/rel/reltool.config +++ b/rel/reltool.config @@ -35,7 +35,8 @@ {app, dynamic_compile, [{incl_cond, include}]}, {app, erlydtl, [{incl_cond, include}]}, {app, parse_trans, [{incl_cond, include}]}, - {app, syntax_tools, [{incl_cond, include}]} + {app, syntax_tools, [{incl_cond, include}]}, + {app, elixir, [{incl_cond, include}]} ]}. {target_dir, "htoad"}.