Current section
Files
Jump to
Current section
Files
src/haki_syntax_compiler.erl
%%%-------------------------------------------------------------------
%%% @doc Using the simple erl_syntax module to build a AST before
%%% compiling the module. This is way more stable than the ASM
%%% compiler and thus should be used for most cases.
%%% @end
%%%-------------------------------------------------------------------
-module(haki_syntax_compiler).
-behavior(haki_compiler).
-include("internal.hrl").
-include("types.hrl").
-export([
compile/2
]).
-spec compile(cache_module_name(), cache_value()) -> compile_ret().
compile(ModName, Val) ->
Forms = forms(ModName, Val),
Compile = ?timed(compile, compile:forms(Forms, ?COMPILER_OPTS)),
case Compile of
{ok, Module, Bin} ->
code:soft_purge(Module),
Filename = atom_to_list(ModName) ++ ".erl",
{module, Module} = code:load_binary(Module, Filename, Bin),
{ok, Bin};
Error ->
error_logger:error_msg("[hakicache] - Could not build module: ~p", [Error]),
Error
end.
forms(ModName, Val) ->
?timed(forms,
begin
ModuleAttr = erl_syntax:attribute(
erl_syntax:atom(module),
[erl_syntax:atom(ModName)]),
GetExport = erl_syntax:arity_qualifier(
erl_syntax:atom(?GET_FUNC),
erl_syntax:integer(0)),
CompileInfoExport = erl_syntax:arity_qualifier(
erl_syntax:atom(?INFO_FUNC),
erl_syntax:integer(0)),
ExportsAttr = erl_syntax:attribute(
erl_syntax:atom(export), [
erl_syntax:list(
[GetExport, CompileInfoExport])]),
Functions = [get_function(Val), compile_info_function()],
Attributes = [ModuleAttr, ExportsAttr],
Module = Attributes ++ Functions,
[erl_syntax:revert(X) || X <- Module]
end).
%% For large lists, parallelize them
get_function(Val) when is_list(Val) andalso length(Val) > ?LARGE_LIST_LENGTH ->
Vals = rpc:pmap({erl_syntax, abstract}, [], Val),
erl_syntax:function(
erl_syntax:atom(?GET_FUNC),
[erl_syntax:clause([], [], [erl_syntax:list(Vals)])]);
get_function(Val) ->
erl_syntax:function(
erl_syntax:atom(?GET_FUNC),
[erl_syntax:clause([], [], [erl_syntax:abstract(Val)])]).
compile_info_function() ->
CompileDate = now_ms(),
erl_syntax:function(
erl_syntax:atom(?INFO_FUNC),
[erl_syntax:clause([], [], [erl_syntax:integer(CompileDate)])]).
now_ms() ->
{MegaSecs, Secs, MicroSecs} = os:timestamp(),
(MegaSecs * 1000000 + Secs) * 1000 + round(MicroSecs / 1000).