diff options
author | José Valim <jose.valim@plataformatec.com.br> | 2013-12-29 15:41:39 +0100 |
---|---|---|
committer | José Valim <jose.valim@plataformatec.com.br> | 2013-12-29 15:41:39 +0100 |
commit | f547ef82e2fd77fccc346f0e57d2c2c31fcd47ad (patch) | |
tree | 275751d9245b7aa2c86fd1577bdbbe84e582bb97 /lib/elixir/src | |
parent | 254065d3c4f1517be76a1828885ccfb68488cdc1 (diff) | |
download | elixir-f547ef82e2fd77fccc346f0e57d2c2c31fcd47ad.tar.gz |
Clean up literal handling and add elixir_bitstring
Diffstat (limited to 'lib/elixir/src')
-rw-r--r-- | lib/elixir/src/elixir_bitstring.erl (renamed from lib/elixir/src/elixir_literal.erl) | 58 | ||||
-rw-r--r-- | lib/elixir/src/elixir_exp.erl | 5 | ||||
-rw-r--r-- | lib/elixir/src/elixir_translator.erl | 48 | ||||
-rw-r--r-- | lib/elixir/src/elixir_utils.erl | 73 |
4 files changed, 65 insertions, 119 deletions
diff --git a/lib/elixir/src/elixir_literal.erl b/lib/elixir/src/elixir_bitstring.erl index 37c3ebfe4..20d40ada7 100644 --- a/lib/elixir/src/elixir_literal.erl +++ b/lib/elixir/src/elixir_bitstring.erl @@ -1,51 +1,11 @@ %% Handle translation of Elixir literals to Erlang AST. --module(elixir_literal). --export([translate/2, expand_bitstr/3]). --import(elixir_translator, [translate_each/2, translate_args/2]). +-module(elixir_bitstring). +-export([translate/3, expand/3]). -include("elixir.hrl"). -%% TODO: Move most of those contents to translation +%% Expansion -translate({ '<<>>', Meta, Args }, S) when is_list(Args) -> - case S#elixir_scope.context of - match -> - build_bitstr(fun elixir_translator:translate_each/2, Args, Meta, S); - _ -> - build_bitstr(fun(X, Acc) -> elixir_translator:translate_arg(X, Acc, S) end, Args, Meta, S) - end; - -translate({ '{}', Meta, Args }, S) when is_list(Args) -> - { TArgs, SE } = translate_args(Args, S), - { { tuple, ?line(Meta), TArgs }, SE }; - -translate({ Left, Right }, S) -> - translate({ '{}', [], [Left, Right]}, S); - -translate([], S) -> - { { nil, 0 }, S }; - -translate([_|_] = Args, S) -> - [RTail|RArgs] = lists:reverse(Args), - - case RTail of - { '|', _, [Left,Right] } -> - RExprs = [Left|RArgs], - TailFun = fun(ST) -> translate_each(Right, ST) end; - _ -> - RExprs = [RTail|RArgs], - TailFun = fun(ST) -> { { nil, 0 }, ST } end - end, - - { Exprs, SE } = translate_args(lists:reverse(RExprs), S), - { Tail, ST } = TailFun(SE), - { elixir_utils:list_to_cons(0, Exprs, Tail), ST }; - -translate(Other, S) -> - { elixir_utils:elixir_to_erl(0, Other, S), S }. - -%% Helpers - -expand_bitstr(Meta, Args, E) -> +expand(Meta, Args, E) -> case E#elixir_env.context of match -> { EArgs, EA } = expand_bitstr(fun elixir_exp:expand/2, Args, [], E), @@ -138,7 +98,15 @@ handle_unknown_bit_info(Meta, { _, ExprMeta, _ } = Expr, T, Size, Types, E) -> expand_bit_info(Meta, List ++ T, Size, Types, E) end. -%% Helpers +%% Translation + +translate(Meta, Args, S) -> + case S#elixir_scope.context of + match -> + build_bitstr(fun elixir_translator:translate_each/2, Args, Meta, S); + _ -> + build_bitstr(fun(X, Acc) -> elixir_translator:translate_arg(X, Acc, S) end, Args, Meta, S) + end. build_bitstr(Fun, Exprs, Meta, S) -> { Final, FinalS } = build_bitstr_each(Fun, Exprs, Meta, S, []), diff --git a/lib/elixir/src/elixir_exp.erl b/lib/elixir/src/elixir_exp.erl index f08b3f5cf..e8e84ff96 100644 --- a/lib/elixir/src/elixir_exp.erl +++ b/lib/elixir/src/elixir_exp.erl @@ -18,7 +18,7 @@ expand({ '{}', Meta, Args }, E) -> { { '{}', Meta, EArgs }, EA }; expand({ '<<>>', Meta, Args }, E) -> - elixir_literal:expand_bitstr(Meta, Args, E); + elixir_bitstring:expand(Meta, Args, E); %% Other operators @@ -386,8 +386,7 @@ expand_many(Args, E) -> %% foo(3, 1) %% 3 %% -%% However, notice that if we are doing an assignment, -%% it behaves as regular expansion. +%% However, lexical information is. expand_arg(Arg, { Acc1, Acc2 }) -> { EArg, EAcc } = expand(Arg, Acc1), { EArg, { elixir_env:mergea(Acc1, EAcc), elixir_env:mergev(Acc2, EAcc) } }. diff --git a/lib/elixir/src/elixir_translator.erl b/lib/elixir/src/elixir_translator.erl index 58afff925..b567ac11d 100644 --- a/lib/elixir/src/elixir_translator.erl +++ b/lib/elixir/src/elixir_translator.erl @@ -18,8 +18,12 @@ translate_each({ '=', Meta, [Left, Right] }, S) -> %% Containers -translate_each({ C, _, _ } = Original, S) when C == '{}'; C == '<<>>' -> - elixir_literal:translate(Original, S); +translate_each({ '{}', Meta, Args }, S) when is_list(Args) -> + { TArgs, SE } = translate_args(Args, S), + { { tuple, ?line(Meta), TArgs }, SE }; + +translate_each({ '<<>>', Meta, Args }, S) when is_list(Args) -> + elixir_bitstring:translate(Meta, Args, S); %% Blocks and scope rewriters @@ -244,11 +248,32 @@ translate_each({ _, _, _ } = Tuple, S) -> %% Literals -translate_each(Literal, S) -> - elixir_literal:translate(Literal, S). +translate_each(List, S) when is_list(List) -> + translate_list(List, S, S, []); + +translate_each({ Left, Right }, S) -> + { TArgs, SE } = translate_args([Left, Right], S), + { { tuple, 0, TArgs }, SE }; + +translate_each(Other, S) -> + { elixir_utils:elixir_to_erl(Other), S }. %% Helpers +translate_list([{ '|', _, [_, _]=Args}], Acc, S, List) -> + { [TLeft,TRight], TAcc } = lists:mapfoldl(fun(X, XA) -> translate_arg(X, XA, S) end, Acc, Args), + { build_list([TLeft|List], TRight), TAcc }; +translate_list([H|T], Acc, S, List) -> + { TH, TAcc } = translate_arg(H, Acc, S), + translate_list(T, TAcc, S, [TH|List]); +translate_list([], Acc, _S, List) -> + { build_list(List, { nil, 0 }), Acc }. + +build_list([H|T], Acc) -> + build_list(T, { cons, 0, H, Acc }); +build_list([], Acc) -> + Acc. + var_kind(Meta, Kind) -> case lists:keyfind(counter, 1, Meta) of { counter, Counter } -> Counter; @@ -278,21 +303,6 @@ unblock(Expr) -> [Expr]. %% Translate args -%% Variables in arguments are not propagated from one -%% argument to the other. For instance: -%% -%% x = 1 -%% foo(x = x + 2, x) -%% x -%% -%% Should be the same as: -%% -%% foo(3, 1) -%% 3 -%% -%% However, notice that if we are doing an assignment, -%% it behaves the same as translate. - translate_arg(Arg, Acc, S) -> { TArg, TAcc } = translate_each(Arg, mergec(S, Acc)), { TArg, mergev(Acc, TAcc) }. diff --git a/lib/elixir/src/elixir_utils.erl b/lib/elixir/src/elixir_utils.erl index ac2e12753..1616bba2c 100644 --- a/lib/elixir/src/elixir_utils.erl +++ b/lib/elixir/src/elixir_utils.erl @@ -1,10 +1,8 @@ %% Convenience functions used throughout elixir source code %% for ast manipulation and querying. -module(elixir_utils). --export([elixir_to_erl/1, elixir_to_erl/2, - get_line/1, split_last/1, elixir_to_erl/3, +-export([elixir_to_erl/1, get_line/1, split_last/1, characters_to_list/1, characters_to_binary/1, - cons_to_list/1, list_to_cons/2, list_to_cons/3, convert_to_boolean/4, returns_boolean/1, file_type/1, file_type/2, relative_to_cwd/1]). -include("elixir.hrl"). @@ -52,59 +50,30 @@ characters_to_binary(Data) -> false -> 'Elixir.String':'from_char_list!'(Data) end. -%% List conversion - -cons_to_list({ nil, _ }) -> []; -cons_to_list({ cons, _, Left, Right }) -> [Left|cons_to_list(Right)]. - -list_to_cons(Line, List) -> - list_to_cons(Line, List, { nil, Line }). - -list_to_cons(Line, List, Tail) -> - lists:foldr(fun(X, Acc) -> - { cons, Line, X, Acc } - end, Tail, List). - %% erl <-> elixir -%% TODO: Clean this up -elixir_to_erl(Tree) -> - elixir_to_erl(Tree, fun(X) -> error({ badarg, X }) end). - -elixir_to_erl(Line, Tree, S) -> - elixir_to_erl(Tree, fun - (X) when is_function(X) -> - elixir_errors:compile_error(Line, S#elixir_scope.file, - "anonymous functions cannot be translated into a quoted expression, got: ~ts", - ['Elixir.Kernel':inspect(X)]); - (X) -> - elixir_errors:compile_error(Line, S#elixir_scope.file, - "cannot translate ~ts into a quoted expression", - ['Elixir.Kernel':inspect(X)]) - end). - -elixir_to_erl(Tree, Fun) when is_tuple(Tree) -> - { tuple, 0, [elixir_to_erl(X, Fun) || X <- tuple_to_list(Tree)] }; - -elixir_to_erl([], _Fun) -> +elixir_to_erl(Tree) when is_tuple(Tree) -> + { tuple, 0, [elixir_to_erl(X) || X <- tuple_to_list(Tree)] }; + +elixir_to_erl([]) -> { nil, 0 }; -elixir_to_erl(Tree, Fun) when is_list(Tree) -> - elixir_to_erl_cons_1(Tree, [], Fun); +elixir_to_erl(Tree) when is_list(Tree) -> + elixir_to_erl_cons_1(Tree, []); -elixir_to_erl(Tree, _Fun) when is_atom(Tree) -> +elixir_to_erl(Tree) when is_atom(Tree) -> { atom, 0, Tree }; -elixir_to_erl(Tree, _Fun) when is_integer(Tree) -> +elixir_to_erl(Tree) when is_integer(Tree) -> { integer, 0, Tree }; -elixir_to_erl(Tree, _Fun) when is_float(Tree) -> +elixir_to_erl(Tree) when is_float(Tree) -> { float, 0, Tree }; -elixir_to_erl(Tree, _Fun) when is_binary(Tree) -> +elixir_to_erl(Tree) when is_binary(Tree) -> { bin, 0, [{ bin_element, 0, { string, 0, binary_to_list(Tree) }, default, default }] }; -elixir_to_erl(Function, Fun) when is_function(Function) -> +elixir_to_erl(Function) when is_function(Function) -> case (erlang:fun_info(Function, type) == { type, external }) andalso (erlang:fun_info(Function, env) == { env, [] }) of true -> @@ -117,21 +86,21 @@ elixir_to_erl(Function, Fun) when is_function(Function) -> { atom, 0, Name }, { integer, 0, Arity } } }; false -> - Fun(Function) + error(badarg) end; -elixir_to_erl(Pid, _Fun) when is_pid(Pid) -> +elixir_to_erl(Pid) when is_pid(Pid) -> ?wrap_call(0, erlang, binary_to_term, [elixir_utils:elixir_to_erl(term_to_binary(Pid))]); -elixir_to_erl(Other, Fun) -> - Fun(Other). +elixir_to_erl(_Other) -> + error(badarg). -elixir_to_erl_cons_1([H|T], Acc, Fun) -> elixir_to_erl_cons_1(T, [H|Acc], Fun); -elixir_to_erl_cons_1(Other, Acc, Fun) -> elixir_to_erl_cons_2(Acc, elixir_to_erl(Other, Fun), Fun). +elixir_to_erl_cons_1([H|T], Acc) -> elixir_to_erl_cons_1(T, [H|Acc]); +elixir_to_erl_cons_1(Other, Acc) -> elixir_to_erl_cons_2(Acc, elixir_to_erl(Other)). -elixir_to_erl_cons_2([H|T], Acc, Fun) -> - elixir_to_erl_cons_2(T, { cons, 0, elixir_to_erl(H, Fun), Acc }, Fun); -elixir_to_erl_cons_2([], Acc, _Fun) -> +elixir_to_erl_cons_2([H|T], Acc) -> + elixir_to_erl_cons_2(T, { cons, 0, elixir_to_erl(H), Acc }); +elixir_to_erl_cons_2([], Acc) -> Acc. %% Boolean checks |