diff --git a/lib/elixir/include/elixir.hrl b/lib/elixir/include/elixir.hrl index db6db735a0..e38b3f0e5d 100644 --- a/lib/elixir/include/elixir.hrl +++ b/lib/elixir/include/elixir.hrl @@ -22,7 +22,7 @@ quote_vars=[], %% a dict of all quoted variables clause_vars=nil, %% a dict of all variables defined in a particular clause extra_guards=nil, %% extra guards from args expansion - counter=0, %% a counter for the variables defined + counter=[], %% a counter for the variables defined file=(<<"nofile">>), %% the current scope filename local=nil, %% the scope to evaluate local functions against aliases=[], %% an orddict with aliases by new -> old names diff --git a/lib/elixir/lib/kernel/parallel_require.ex b/lib/elixir/lib/kernel/parallel_require.ex index 566acdafff..0f7c8bf5ef 100644 --- a/lib/elixir/lib/kernel/parallel_require.ex +++ b/lib/elixir/lib/kernel/parallel_require.ex @@ -27,10 +27,9 @@ defmodule Kernel.ParallelRequire do child = spawn_link fn -> try do - new = Code.require_file(h) - result = (new || []) ++ result + new = Code.require_file(h) callback.(h) - parent <- { :required, self } + parent <- { :required, self, new } catch kind, reason -> parent <- { :failure, self, kind, reason, System.stacktrace } @@ -42,8 +41,8 @@ defmodule Kernel.ParallelRequire do defp wait_for_messages(files, waiting, callback, result) do receive do - { :required, child } -> - spawn_requires(files, List.delete(waiting, child), callback, result) + { :required, child, new } -> + spawn_requires(files, List.delete(waiting, child), callback, (new || []) ++ result) { :failure, _child, kind, reason, stacktrace } -> :erlang.raise(kind, reason, stacktrace) end diff --git a/lib/elixir/lib/list.ex b/lib/elixir/lib/list.ex index 867229a449..6f29ac81eb 100644 --- a/lib/elixir/lib/list.ex +++ b/lib/elixir/lib/list.ex @@ -271,7 +271,7 @@ defmodule List do def range(first, last, step // nil) def range(first, last, step) when is_integer(first) and is_integer(last) and first <= last do - step = case step do + case step do nil -> :lists.seq(first, last, 1) x when x < 0 -> @@ -282,7 +282,7 @@ defmodule List do end def range(first, last, step) when is_integer(first) and is_integer(last) and first > last do - step = case step do + case step do nil -> :lists.seq(first, last, -1) x when x > 0 -> diff --git a/lib/elixir/src/elixir.erl b/lib/elixir/src/elixir.erl index 16d944dcce..751d9a45ab 100644 --- a/lib/elixir/src/elixir.erl +++ b/lib/elixir/src/elixir.erl @@ -104,7 +104,7 @@ eval_forms(Tree, Binding, RawScope) -> temp_vars=[], quote_vars=[], clause_vars=nil, - counter=0 + counter=[] }, { ParseTree, NewScope } = elixir_translator:translate(Tree, Scope), case ParseTree of @@ -125,9 +125,10 @@ binding_dict([], Dict) -> Dict. final_binding(Binding, Vars) -> final_binding(Binding, [], Binding, Vars). final_binding([{Var,_}|T], Acc, Binding, Vars) -> - case atom_to_list(Var) of - "_@" ++ _ -> final_binding(T, Acc, Binding, Vars); - _ -> + case lists:member($@, atom_to_list(Var)) of + true -> + final_binding(T, Acc, Binding, Vars); + false -> RealName = orddict:fetch(Var, Vars), RealValue = proplists:get_value(RealName, Binding, nil), final_binding(T, [{Var, RealValue}|Acc], Binding, Vars) diff --git a/lib/elixir/src/elixir_def_defaults.erl b/lib/elixir/src/elixir_def_defaults.erl index 58217dc238..8ffd828173 100644 --- a/lib/elixir/src/elixir_def_defaults.erl +++ b/lib/elixir/src/elixir_def_defaults.erl @@ -15,8 +15,7 @@ unpack_each(Kind, Name, [{'//', Line, [Expr, _]}|T] = List, Acc, Clauses, S) -> Base = build_match(Acc, Line, []), { Args, Invoke } = extract_defaults(List, Line, length(Base), [], []), - SM = S#elixir_scope{counter=length(Base)}, - { DefArgs, SA } = elixir_clauses:assigns(fun elixir_translator:translate/2, Base ++ Args, SM), + { DefArgs, SA } = elixir_clauses:assigns(fun elixir_translator:translate/2, Base ++ Args, S), { InvokeArgs, _ } = elixir_translator:translate_args(Base ++ Invoke, SA), Call = { call, Line, @@ -39,7 +38,7 @@ extract_defaults([{'//', _, [_Expr, Default]}|T], Line, Counter, NewArgs, NewInv extract_defaults(T, Line, Counter, NewArgs, [Default|NewInvoke]); extract_defaults([_|T], Line, Counter, NewArgs, NewInvoke) -> - H = { ?ELIXIR_ATOM_CONCAT(["_@", Counter]), Line, nil }, + H = { ?ELIXIR_ATOM_CONCAT(["_@D", Counter]), Line, nil }, extract_defaults(T, Line, Counter + 1, [H|NewArgs], [H|NewInvoke]); extract_defaults([], _Line, _Counter, NewArgs, NewInvoke) -> @@ -50,7 +49,7 @@ extract_defaults([], _Line, _Counter, NewArgs, NewInvoke) -> build_match([], _Line, Acc) -> Acc; build_match([_|T], Line, Acc) -> - Var = { ?ELIXIR_ATOM_CONCAT(["_@", length(T)]), Line, nil }, + Var = { ?ELIXIR_ATOM_CONCAT(["_@D", length(T)]), Line, nil }, build_match(T, Line, [Var|Acc]). % Given the invoked function name based on the kind diff --git a/lib/elixir/src/elixir_errors.erl b/lib/elixir/src/elixir_errors.erl index 1397703604..58b37f98fc 100644 --- a/lib/elixir/src/elixir_errors.erl +++ b/lib/elixir/src/elixir_errors.erl @@ -106,6 +106,11 @@ handle_file_warning(_, File, {Line,erl_lint,{undefined_behaviour,Module}}) -> io:format(file_format(Line, File, Message)); %% Default behavior +handle_file_warning(_, File, {Line,erl_lint,{unused_var,Var}}) -> + List = lists:takewhile(fun(X) -> X /= $@ end, atom_to_list(Var)), + Message = format_error(erl_lint, { unused_var, list_to_atom(List) }), + io:format(file_format(Line, File, Message)); + handle_file_warning(_, File, {Line,Module,Desc}) -> Message = format_error(Module, Desc), io:format(file_format(Line, File, Message)). diff --git a/lib/elixir/src/elixir_scope.erl b/lib/elixir/src/elixir_scope.erl index 1b1db4957e..7709f79f0f 100644 --- a/lib/elixir/src/elixir_scope.erl +++ b/lib/elixir/src/elixir_scope.erl @@ -1,8 +1,10 @@ + %% Convenience functions used to manipulate scope %% and its variables. -module(elixir_scope). -export([translate_var/4, build_erl_var/2, build_ex_var/2, + build_erl_var/3, build_ex_var/3, serialize/1, deserialize/1, deserialize/2, to_erl_env/1, to_ex_env/1, filename/1, umergev/2, umergec/2, merge_clause_vars/2 @@ -24,9 +26,11 @@ translate_var(Line, Name, Kind, S) -> { true, { ok, Kind } } -> { {var, Line, orddict:fetch(Name, Vars) }, S }; { Else, _ } -> - { NewVar, NS } = case Else or S#elixir_scope.noname of - true -> build_erl_var(Line, S); - false -> { {var, Line, Name}, S } + { NewVar, NS } = if + Else -> build_erl_var(Line, Name, S); + Kind == quoted -> build_erl_var(Line, S); + S#elixir_scope.noname -> build_erl_var(Line, Name, S); + true -> { {var, Line, Name}, S } end, RealName = element(3, NewVar), ClauseVars = S#elixir_scope.clause_vars, @@ -49,14 +53,24 @@ translate_var(Line, Name, Kind, S) -> % Handle variables translation -build_erl_var(Line, #elixir_scope{counter=Counter} = S) -> - NS = S#elixir_scope{counter=Counter+1}, - Var = { var, Line, ?ELIXIR_ATOM_CONCAT(["_@", Counter]) }, +build_ex_var(Line, S) -> build_ex_var(Line, "_", '', S). +build_erl_var(Line, S) -> build_erl_var(Line, "_", '', S). + +build_ex_var(Line, Key, S) -> build_ex_var(Line, "", Key, S). +build_erl_var(Line, Key, S) -> build_erl_var(Line, "", Key, S). + +build_var_counter(Key, #elixir_scope{counter=Counter} = S) -> + New = orddict:update_counter(Key, 1, Counter), + { orddict:fetch(Key, New), S#elixir_scope{counter=New} }. + +build_erl_var(Line, Prefix, Key, S) -> + { Counter, NS } = build_var_counter(Key, S), + Var = { var, Line, ?ELIXIR_ATOM_CONCAT([Prefix, Key, "@", Counter]) }, { Var, NS }. -build_ex_var(Line, #elixir_scope{counter=Counter} = S) -> - NS = S#elixir_scope{counter=Counter+1}, - Var = { ?ELIXIR_ATOM_CONCAT(["_@", Counter]), Line, nil }, +build_ex_var(Line, Prefix, Key, S) -> + { Counter, NS } = build_var_counter(Key, S), + Var = { ?ELIXIR_ATOM_CONCAT([Prefix, Key, "@", Counter]), Line, nil }, { Var, NS }. % Handle Macro.Env conversion @@ -97,7 +111,7 @@ deserialize({ File, Functions, CheckClauses, Requires, Macros, Aliases, Schedule aliases=Aliases, scheduled=Scheduled, vars=orddict:from_list(Vars), - counter=length(Vars) + counter=[{'',length(Vars)}] }. % Receives two scopes and return a new scope based on the second @@ -141,10 +155,7 @@ clause_var_merger({ Var, _ }, K1, K2) -> var_merger(Var, Var, K2) -> K2; var_merger(Var, K1, Var) -> K1; var_merger(_Var, K1, K2) -> - V1 = var_number(atom_to_list(K1)), - V2 = var_number(atom_to_list(K2)), - if V1 > V2 -> K1; - true -> K2 + case atom_to_list(K1) > atom_to_list(K2) of + true -> K1; + false -> K2 end. - -var_number([_,_|T]) -> list_to_integer(T). \ No newline at end of file diff --git a/lib/elixir/test/elixir/uri_test.exs b/lib/elixir/test/elixir/uri_test.exs index 0a7b0987e6..6e888d579f 100644 --- a/lib/elixir/test/elixir/uri_test.exs +++ b/lib/elixir/test/elixir/uri_test.exs @@ -1,3 +1,5 @@ +Code.require_file "../test_helper.exs", __FILE__ + defmodule URITest do use ExUnit.Case, async: true diff --git a/lib/ex_unit/lib/ex_unit/assertions.ex b/lib/ex_unit/lib/ex_unit/assertions.ex index 48a5d2b041..3ff544cc1c 100644 --- a/lib/ex_unit/lib/ex_unit/assertions.ex +++ b/lib/ex_unit/lib/ex_unit/assertions.ex @@ -69,15 +69,8 @@ defmodule ExUnit.Assertions do quote do: (var!(op) == :! or var!(op) == :not) end - defp translate_assertion({ :=, _, [expected, received] }, _else) do - quote do - unquote(expected) = try do - unquote(expected) = unquote(received) - rescue - x in [MatchError] -> - raise ExUnit.AssertionError, message: x.message - end - end + defp translate_assertion({ :=, _, [_, _] } = expr, _else) do + expr end defp translate_assertion({ :==, _, [left, right] }, _else) do @@ -132,7 +125,7 @@ defmodule ExUnit.Assertions do unquote(expected) = x = unquote(received) flunk "Unexpected right side #{inspect x} match" rescue - x in [MatchError] -> true + _ in [MatchError] -> true end end end diff --git a/lib/ex_unit/test/ex_unit/assertions_test.exs b/lib/ex_unit/test/ex_unit/assertions_test.exs index baec9b3b1c..40af2d24cc 100644 --- a/lib/ex_unit/test/ex_unit/assertions_test.exs +++ b/lib/ex_unit/test/ex_unit/assertions_test.exs @@ -75,16 +75,6 @@ defmodule ExUnit.AssertionsTest do { 2, 1 } = (assert { 2, 1 } = Value.tuple) end - test :assert_match_when_different do - try do - assert {_, 2} = Value.tuple - raise "failed" - rescue - error in [ExUnit.AssertionError] -> - "no match of right hand side value: {2,1}" = error.message - end - end - test :assert_received do self <- :hello :hello = assert_received :hello