Compare commits
5 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0ed11ba68c | ||
![]() |
50fbda3dc8 | ||
![]() |
fed8522774 | ||
![]() |
aa8b2088cf | ||
![]() |
0d0edc4461 |
3 changed files with 157 additions and 7 deletions
2
Makefile
2
Makefile
|
@ -16,7 +16,7 @@ ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt
|
||||||
|
|
||||||
.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps escript
|
.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps escript
|
||||||
|
|
||||||
all: compile test dialyzer
|
all: compile test doc dialyzer
|
||||||
|
|
||||||
get-deps:
|
get-deps:
|
||||||
$(REBAR) get-deps
|
$(REBAR) get-deps
|
||||||
|
|
107
src/ec_compile.erl
Normal file
107
src/ec_compile.erl
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author Eric Merritt <>
|
||||||
|
%%% @copyright (C) 2011, Erlware, LLC.
|
||||||
|
%%% @doc
|
||||||
|
%%% These are various utility functions to help with compiling and
|
||||||
|
%%% decompiling erlang source. They are mostly useful to the
|
||||||
|
%%% language/parse transform implementor.
|
||||||
|
%%% @end
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(ec_compile).
|
||||||
|
|
||||||
|
-export([beam_to_erl_source/2,
|
||||||
|
erl_source_to_core_ast/1,
|
||||||
|
erl_source_to_erl_ast/1,
|
||||||
|
erl_source_to_asm/1,
|
||||||
|
erl_string_to_core_ast/1,
|
||||||
|
erl_string_to_erl_ast/1,
|
||||||
|
erl_string_to_asm/1]).
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
%%% API
|
||||||
|
%%%===================================================================
|
||||||
|
|
||||||
|
%% @doc decompile a beam file that has been compiled with +debug_info
|
||||||
|
%% into a erlang source file
|
||||||
|
%%
|
||||||
|
%% @param BeamFName the name of the beamfile
|
||||||
|
%% @param ErlFName the name of the erlang file where the generated
|
||||||
|
%% source file will be output. This should *not* be the same as the
|
||||||
|
%% source file that created the beamfile unless you want to overwrite
|
||||||
|
%% it.
|
||||||
|
-spec beam_to_erl_source(string(), string()) -> ok | term().
|
||||||
|
beam_to_erl_source(BeamFName, ErlFName) ->
|
||||||
|
case beam_lib:chunks(BeamFName, [abstract_code]) of
|
||||||
|
{ok, {_, [{abstract_code, {raw_abstract_v1,Forms}}]}} ->
|
||||||
|
Src =
|
||||||
|
erl_prettypr:format(erl_syntax:form_list(tl(Forms))),
|
||||||
|
{ok, Fd} = file:open(ErlFName, [write]),
|
||||||
|
io:fwrite(Fd, "~s~n", [Src]),
|
||||||
|
file:close(Fd);
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end.
|
||||||
|
|
||||||
|
%% @doc compile an erlang source file into a Core Erlang AST
|
||||||
|
%%
|
||||||
|
%% @param Path - The path to the erlang source file
|
||||||
|
-spec erl_source_to_core_ast(file:filename()) -> CoreAst::term().
|
||||||
|
erl_source_to_core_ast(Path) ->
|
||||||
|
{ok, Contents} = file:read_file(Path),
|
||||||
|
erl_string_to_core_ast(binary_to_list(Contents)).
|
||||||
|
|
||||||
|
%% @doc compile an erlang source file into an Erlang AST
|
||||||
|
%%
|
||||||
|
%% @param Path - The path to the erlang source file
|
||||||
|
-spec erl_source_to_erl_ast(file:filename()) -> ErlangAst::term().
|
||||||
|
erl_source_to_erl_ast(Path) ->
|
||||||
|
{ok, Contents} = file:read_file(Path),
|
||||||
|
erl_string_to_erl_ast(binary_to_list(Contents)).
|
||||||
|
|
||||||
|
%% @doc compile an erlang source file into erlang terms that represent
|
||||||
|
%% the relevant ASM
|
||||||
|
%%
|
||||||
|
%% @param Path - The path to the erlang source file
|
||||||
|
-spec erl_source_to_asm(file:filename()) -> ErlangAsm::term().
|
||||||
|
erl_source_to_asm(Path) ->
|
||||||
|
{ok, Contents} = file:read_file(Path),
|
||||||
|
erl_string_to_asm(binary_to_list(Contents)).
|
||||||
|
|
||||||
|
%% @doc compile a string representing an erlang expression into an
|
||||||
|
%% Erlang AST
|
||||||
|
%%
|
||||||
|
%% @param StringExpr - The path to the erlang source file
|
||||||
|
-spec erl_string_to_erl_ast(string()) -> ErlangAst::term().
|
||||||
|
erl_string_to_erl_ast(StringExpr) ->
|
||||||
|
Forms0 =
|
||||||
|
lists:foldl(fun(<<>>, Acc) ->
|
||||||
|
Acc;
|
||||||
|
(<<"\n\n">>, Acc) ->
|
||||||
|
Acc;
|
||||||
|
(El, Acc) ->
|
||||||
|
{ok, Tokens, _} =
|
||||||
|
erl_scan:string(binary_to_list(El)
|
||||||
|
++ "."),
|
||||||
|
[Tokens | Acc]
|
||||||
|
end, [], re:split(StringExpr, "\\.\n")),
|
||||||
|
%% No need to reverse. This will rereverse for us
|
||||||
|
lists:foldl(fun(Form, Forms) ->
|
||||||
|
{ok, ErlAST} = erl_parse:parse_form(Form),
|
||||||
|
[ErlAST | Forms]
|
||||||
|
end, [], Forms0).
|
||||||
|
|
||||||
|
%% @doc compile a string representing an erlang expression into a
|
||||||
|
%% Core Erlang AST
|
||||||
|
%%
|
||||||
|
%% @param StringExpr - The path to the erlang source file
|
||||||
|
-spec erl_string_to_core_ast(string()) -> CoreAst::term().
|
||||||
|
erl_string_to_core_ast(StringExpr) ->
|
||||||
|
compile:forms(erl_string_to_erl_ast(StringExpr), [to_core]).
|
||||||
|
|
||||||
|
%% @doc compile a string representing an erlang expression into a term
|
||||||
|
%% that represents the ASM
|
||||||
|
%%
|
||||||
|
%% @param StringExpr - The path to the erlang source file
|
||||||
|
-spec erl_string_to_asm(string()) -> ErlangAsm::term().
|
||||||
|
erl_string_to_asm(StringExpr) ->
|
||||||
|
compile:forms(erl_string_to_erl_ast(StringExpr), ['S']).
|
|
@ -8,6 +8,7 @@
|
||||||
-module(ec_semver).
|
-module(ec_semver).
|
||||||
|
|
||||||
-export([parse/1,
|
-export([parse/1,
|
||||||
|
format/1,
|
||||||
eql/2,
|
eql/2,
|
||||||
gt/2,
|
gt/2,
|
||||||
gte/2,
|
gte/2,
|
||||||
|
@ -54,6 +55,24 @@ parse(Version) when erlang:is_binary(Version) ->
|
||||||
parse(Version) ->
|
parse(Version) ->
|
||||||
Version.
|
Version.
|
||||||
|
|
||||||
|
-spec format(semver()) -> iolist().
|
||||||
|
format({Maj, {AlphaPart, BuildPart}})
|
||||||
|
when erlang:is_integer(Maj) ->
|
||||||
|
[erlang:integer_to_list(Maj),
|
||||||
|
format_vsn_rest(<<"-">>, AlphaPart),
|
||||||
|
format_vsn_rest(<<"+">>, BuildPart)];
|
||||||
|
format({{Maj, Min}, {AlphaPart, BuildPart}}) ->
|
||||||
|
[erlang:integer_to_list(Maj), ".",
|
||||||
|
erlang:integer_to_list(Min),
|
||||||
|
format_vsn_rest(<<"-">>, AlphaPart),
|
||||||
|
format_vsn_rest(<<"+">>, BuildPart)];
|
||||||
|
format({{Maj, Min, Patch}, {AlphaPart, BuildPart}}) ->
|
||||||
|
[erlang:integer_to_list(Maj), ".",
|
||||||
|
erlang:integer_to_list(Min), ".",
|
||||||
|
erlang:integer_to_list(Patch),
|
||||||
|
format_vsn_rest(<<"-">>, AlphaPart),
|
||||||
|
format_vsn_rest(<<"+">>, BuildPart)].
|
||||||
|
|
||||||
%% @doc test for quality between semver versions
|
%% @doc test for quality between semver versions
|
||||||
-spec eql(any_version(), any_version()) -> boolean().
|
-spec eql(any_version(), any_version()) -> boolean().
|
||||||
eql(VsnA, VsnB) ->
|
eql(VsnA, VsnB) ->
|
||||||
|
@ -141,8 +160,8 @@ between(Vsn1, Vsn2, VsnMatch) ->
|
||||||
%% revisions and "~> 2.6.5" is pessimistic about future minor
|
%% revisions and "~> 2.6.5" is pessimistic about future minor
|
||||||
%% revisions.
|
%% revisions.
|
||||||
%%
|
%%
|
||||||
%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0
|
%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0
|
||||||
%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0
|
%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0
|
||||||
pes(VsnA, VsnB) ->
|
pes(VsnA, VsnB) ->
|
||||||
internal_pes(parse(VsnA), parse(VsnB)).
|
internal_pes(parse(VsnA), parse(VsnB)).
|
||||||
|
|
||||||
|
@ -189,6 +208,19 @@ format_alpha_part([<<".">>, AlphaPart]) ->
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Internal Functions
|
%%% Internal Functions
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
-spec to_list(integer() | binary() | string()) -> string().
|
||||||
|
to_list(Detail) when erlang:is_integer(Detail) ->
|
||||||
|
erlang:integer_to_list(Detail);
|
||||||
|
to_list(Detail) ->
|
||||||
|
Detail.
|
||||||
|
|
||||||
|
-spec format_vsn_rest(binary() | string(), [integer() | binary()]) -> iolist().
|
||||||
|
format_vsn_rest(_TypeMark, []) ->
|
||||||
|
[];
|
||||||
|
format_vsn_rest(TypeMark, [Head | Rest]) ->
|
||||||
|
[TypeMark, Head |
|
||||||
|
[[".", to_list(Detail)] || Detail <- Rest]].
|
||||||
|
|
||||||
%% @doc normalize the semver so they can be compared
|
%% @doc normalize the semver so they can be compared
|
||||||
-spec normalize(semver()) -> semver().
|
-spec normalize(semver()) -> semver().
|
||||||
normalize({Vsn, Rest})
|
normalize({Vsn, Rest})
|
||||||
|
@ -212,9 +244,6 @@ internal_pes(VsnA, {{LM, LMI, LP}, _}) ->
|
||||||
internal_pes(Vsn, LVsn) ->
|
internal_pes(Vsn, LVsn) ->
|
||||||
gte(Vsn, LVsn).
|
gte(Vsn, LVsn).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Test Functions
|
%%% Test Functions
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
@ -242,7 +271,6 @@ eql_test() ->
|
||||||
?assertMatch(true, not eql("1.0.0+build.1",
|
?assertMatch(true, not eql("1.0.0+build.1",
|
||||||
"1.0.1+build.2")).
|
"1.0.1+build.2")).
|
||||||
|
|
||||||
|
|
||||||
gt_test() ->
|
gt_test() ->
|
||||||
?assertMatch(true, gt("1.0.0-alpha.1",
|
?assertMatch(true, gt("1.0.0-alpha.1",
|
||||||
"1.0.0-alpha")),
|
"1.0.0-alpha")),
|
||||||
|
@ -523,4 +551,19 @@ pes_test() ->
|
||||||
?assertMatch(true, not pes("2.7", "2.6.5")),
|
?assertMatch(true, not pes("2.7", "2.6.5")),
|
||||||
?assertMatch(true, not pes("2.5", "2.6.5")).
|
?assertMatch(true, not pes("2.5", "2.6.5")).
|
||||||
|
|
||||||
|
version_format_test() ->
|
||||||
|
?assertEqual(["1", [], []], format({1, {[],[]}})),
|
||||||
|
?assertEqual(["1", ".", "2", ".", "34", [], []], format({{1,2,34},{[],[]}})),
|
||||||
|
?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))),
|
||||||
|
?assertEqual(<<"1.2">>, erlang:iolist_to_binary(format({{1,2}, {[],[]}}))),
|
||||||
|
?assertEqual(<<"1.2.2">>, erlang:iolist_to_binary(format({{1,2,2}, {[],[]}}))),
|
||||||
|
?assertEqual(<<"1.99.2">>, erlang:iolist_to_binary(format({{1,99,2}, {[],[]}}))),
|
||||||
|
?assertEqual(<<"1.99.2-alpha">>, erlang:iolist_to_binary(format({{1,99,2}, {["alpha"],[]}}))),
|
||||||
|
?assertEqual(<<"1.99.2-alpha.1">>, erlang:iolist_to_binary(format({{1,99,2}, {["alpha",1], []}}))),
|
||||||
|
?assertEqual(<<"1.99.2+build.1.a36">>,
|
||||||
|
erlang:iolist_to_binary(format({{1,99,2}, {[], ["build", 1, "a36"]}}))),
|
||||||
|
?assertEqual(<<"1.99.2-alpha.1+build.1.a36">>,
|
||||||
|
erlang:iolist_to_binary(format({{1,99,2}, {["alpha", 1], ["build", 1, "a36"]}}))),
|
||||||
|
?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))).
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue