summaryrefslogtreecommitdiff
path: root/lib/elixir/src
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@plataformatec.com.br>2013-12-29 15:41:39 +0100
committerJosé Valim <jose.valim@plataformatec.com.br>2013-12-29 15:41:39 +0100
commitf547ef82e2fd77fccc346f0e57d2c2c31fcd47ad (patch)
tree275751d9245b7aa2c86fd1577bdbbe84e582bb97 /lib/elixir/src
parent254065d3c4f1517be76a1828885ccfb68488cdc1 (diff)
downloadelixir-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.erl5
-rw-r--r--lib/elixir/src/elixir_translator.erl48
-rw-r--r--lib/elixir/src/elixir_utils.erl73
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