Skip to content

Commit 82cf622

Browse files
author
José Valim
committed
Enable record rewriter inference
1 parent 088ef2f commit 82cf622

File tree

5 files changed

+45
-22
lines changed

5 files changed

+45
-22
lines changed

lib/elixir/lib/kernel/record_rewriter.ex

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,11 @@ defmodule Kernel.RecordRewriter do
171171
end
172172

173173
defp optimize_expr({ :fun, line, { :clauses, clauses } }, dict) do
174-
tuples = lc clause inlist clauses, do: optimize_clause(clause, dict)
175-
clauses = lc { clause, _, _ } inlist tuples, do: clause
174+
clauses = lc clause inlist clauses do
175+
{ clause, _, _ } = optimize_clause(clause, dict)
176+
clause
177+
end
178+
176179
{ { :fun, line, { :clauses, clauses } }, dict, nil }
177180
end
178181

lib/elixir/src/elixir_compiler.erl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ core_main() ->
178178
"lib/elixir/lib/system.ex",
179179
"lib/elixir/lib/kernel/cli.ex",
180180
"lib/elixir/lib/kernel/error_handler.ex",
181-
"lib/elixir/lib/kernel/parallel_compiler.ex"
181+
"lib/elixir/lib/kernel/parallel_compiler.ex",
182+
"lib/elixir/lib/kernel/record_rewriter.ex"
182183
].
183184

184185
%% ERROR HANDLING

lib/elixir/src/elixir_def.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ store_definition(Kind, Line, Module, Name, Args, Guards, Body, RawS) ->
9393
end,
9494

9595
[store_each(false, Kind, File, Location, Table, 0,
96-
function_for_default(Kind, Name, Default)) || Default <- Defaults],
96+
default_function_for(Kind, Name, Default)) || Default <- Defaults],
9797

9898
{ Name, Arity }.
9999

@@ -241,11 +241,11 @@ function_for_stored_definition({{Name, Arity}, _, Line, _, _, Location, _, Claus
241241
]
242242
}.
243243

244-
function_for_default(Kind, Name, { clause, Line, Args, _Guards, _Exprs } = Clause)
244+
default_function_for(Kind, Name, { clause, Line, Args, _Guards, _Exprs } = Clause)
245245
when Kind == defmacro; Kind == defmacrop ->
246246
{ function, Line, Name, length(Args) - 1, [Clause] };
247247

248-
function_for_default(_, Name, { clause, Line, Args, _Guards, _Exprs } = Clause) ->
248+
default_function_for(_, Name, { clause, Line, Args, _Guards, _Exprs } = Clause) ->
249249
{ function, Line, Name, length(Args), [Clause] }.
250250

251251
%% Store each definition in the table.

lib/elixir/src/elixir_module.erl

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,8 @@ docs_table(Module) ->
4040
%% will be passed to the invoked function.
4141

4242
translate(Line, Ref, Block, S) ->
43-
MetaBlock = elixir_tree_helpers:abstract_syntax(Block),
44-
MetaS = elixir_scope:serialize(S),
45-
46-
{ Vars, _ } = orddict:fold(fun({ Key, Kind }, Value, { Acc, Counter }) ->
47-
{ { cons, Line, { tuple, Line, [
48-
{ atom, Line, Key },
49-
{ atom, Line, Kind },
50-
{ atom, Line, ?ELIXIR_ATOM_CONCAT(["_@", Counter]) },
51-
{ var, Line, Value }
52-
] }, Acc }, Counter + 1 }
53-
end, { { nil, Line }, 0 }, S#elixir_scope.vars),
43+
MetaBlock = elixir_tree_helpers:abstract_syntax(Block),
44+
{ MetaS, Vars } = elixir_scope:serialize_with_vars(Line, S),
5445

5546
Args = [{integer, Line, Line}, Ref, MetaBlock, Vars, MetaS],
5647
?ELIXIR_WRAP_CALL(Line, ?MODULE, compile, Args).
@@ -94,7 +85,7 @@ compile(Line, Other, _Block, _Vars, #elixir_scope{file=File}) ->
9485

9586
compile(Line, Module, Block, Vars, RawS) ->
9687
Dict = [{ { Name, Kind }, Value } || { Name, Kind, Value, _ } <- Vars],
97-
S = elixir_scope:deserialize(RawS, Dict),
88+
S = elixir_scope:deserialize_with_vars(RawS, Dict),
9889
compile(Line, Module, Block, Vars, S).
9990

10091
%% Hook that builds both attribute and functions and set up common hooks.
@@ -145,7 +136,12 @@ eval_form(Line, Module, Block, Vars, RawS) ->
145136
Value.
146137

147138
%% Return the form with exports and function declarations.
148-
functions_form(Line, File, Module, Export, Private, Def, Defmacro, Defmacrop, Functions, C) ->
139+
functions_form(Line, File, Module, Export, Private, Def, Defmacro, Defmacrop, RawFunctions, C) ->
140+
Functions = case elixir_compiler:get_opt(internal, C) of
141+
true -> RawFunctions;
142+
false -> record_rewrite_functions(RawFunctions)
143+
end,
144+
149145
{ FinalExport, FinalFunctions } =
150146
add_info_function(Line, File, Module, Export, Functions, Def, Defmacro, C),
151147

@@ -156,6 +152,17 @@ functions_form(Line, File, Module, Export, Private, Def, Defmacro, Defmacrop, Fu
156152
{attribute, Line, export, lists:sort(FinalExport)} | FinalFunctions
157153
] }.
158154

155+
record_rewrite_functions(Functions) ->
156+
lists:map(fun
157+
({ function, Line, Name, Arity, Clauses }) ->
158+
Rewriten = lists:map(fun(Clause) ->
159+
{ C, _, _ } = 'Elixir.Kernel.RecordRewriter':optimize_clause(Clause),
160+
C
161+
end, Clauses),
162+
{ function, Line, Name, Arity, Rewriten };
163+
(Other) -> Other
164+
end, Functions).
165+
159166
%% Add attributes handling to the form
160167

161168
attributes_form(Line, _File, Module, Current) ->

lib/elixir/src/elixir_scope.erl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
build_erl_var/2, build_ex_var/2,
66
build_erl_var/3, build_ex_var/3,
77
build_erl_var/4, build_ex_var/4,
8-
serialize/1, deserialize/1, deserialize/2,
8+
serialize/1, deserialize/1,
9+
serialize_with_vars/2, deserialize_with_vars/2,
910
to_erl_env/1, to_ex_env/1, filename/1,
1011
umergev/2, umergec/2, merge_clause_vars/2
1112
]).
@@ -97,11 +98,22 @@ serialize(S) ->
9798
S#elixir_scope.requires, S#elixir_scope.macros, S#elixir_scope.aliases, S#elixir_scope.scheduled }
9899
).
99100

101+
serialize_with_vars(Line, S) ->
102+
{ Vars, _ } = orddict:fold(fun({ Key, Kind }, Value, { Acc, Counter }) ->
103+
{ { cons, Line, { tuple, Line, [
104+
{ atom, Line, Key },
105+
{ atom, Line, Kind },
106+
{ atom, Line, ?ELIXIR_ATOM_CONCAT(["_@", Counter]) },
107+
{ var, Line, Value }
108+
] }, Acc }, Counter + 1 }
109+
end, { { nil, Line }, 0 }, S#elixir_scope.vars),
110+
{ serialize(S), Vars }.
111+
100112
% Fill in the scope with the variables serialization set in serialize_scope.
101113

102-
deserialize(Tuple) -> deserialize(Tuple, []).
114+
deserialize(Tuple) -> deserialize_with_vars(Tuple, []).
103115

104-
deserialize({ File, Functions, CheckClauses, Requires, Macros, Aliases, Scheduled }, Vars) ->
116+
deserialize_with_vars({ File, Functions, CheckClauses, Requires, Macros, Aliases, Scheduled }, Vars) ->
105117
#elixir_scope{
106118
file=File,
107119
functions=Functions,

0 commit comments

Comments
 (0)