Skip to content

Commit 5bd12f9

Browse files
author
José Valim
committed
Move lexical tracker to scope
1 parent 3c151d5 commit 5bd12f9

File tree

12 files changed

+82
-87
lines changed

12 files changed

+82
-87
lines changed

lib/elixir/include/elixir.hrl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
context_modules=[], %% modules defined in the current context
2727
macro_aliases=[], %% keep aliases defined inside a macro
2828
macro_counter=0, %% macros expansions counter
29+
lexical_tracker=nil, %% holds the lexical tracker pid
2930
aliases, %% an orddict with aliases by new -> old names
3031
file, %% the current scope filename
3132
requires, %% a set with modules required

lib/elixir/lib/macro.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,15 +536,15 @@ defmodule Macro do
536536
defp expand_once({ :__aliases__, _, _ } = original, env, cache) do
537537
case :elixir_aliases.expand(original, env.aliases, env.macro_aliases) do
538538
receiver when is_atom(receiver) ->
539-
:elixir_lexical.record_alias(env.file, receiver)
539+
:elixir_lexical.record_alias(receiver, env.lexical_tracker)
540540
{ receiver, true, cache }
541541
aliases ->
542542
aliases = lc alias inlist aliases, do: elem(expand_once(alias, env, cache), 0)
543543

544544
case :lists.all(&is_atom/1, aliases) do
545545
true ->
546546
receiver = :elixir_aliases.concat(aliases)
547-
:elixir_lexical.record_alias(env.file, receiver)
547+
:elixir_lexical.record_alias(receiver, env.lexical_tracker)
548548
{ receiver, true, cache }
549549
false -> { original, false, cache }
550550
end

lib/elixir/lib/macro/env.ex

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ defmodule Macro.Env do
3434
@type macros :: [{ module, [name_arity] }]
3535
@type context_modules :: [module]
3636
@type vars :: [{ atom, atom }]
37+
@type lexical_tracker :: pid
3738

38-
fields = [:module, :file, :line, :function, :aliases, :context, :requires,
39-
:functions, :macros, :context_modules, :macro_aliases, :vars]
39+
fields = [:module, :file, :line, :function, :aliases, :context, :requires, :functions,
40+
:macros, :context_modules, :macro_aliases, :vars, :lexical_tracker]
4041

4142
types = quote do: [module: module, file: file, line: line,
4243
function: name_arity, aliases: aliases, requires: requires,
4344
functions: functions, macros: macros, context_modules: context_modules,
44-
macro_aliases: aliases, vars: vars]
45+
macro_aliases: aliases, vars: vars, lexical_tracker: lexical_tracker]
4546

4647
Record.deffunctions(fields, __MODULE__)
4748
Record.deftypes(fields, types, __MODULE__)

lib/elixir/src/elixir_code_server.erl

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
at_exit=[],
1111
pool={[],0},
1212
compiler_options=[{docs,true},{debug_info,true},{warnings_as_errors,false}],
13-
erl_compiler_options=nil,
14-
lexical=[]
13+
erl_compiler_options=nil
1514
}).
1615

1716
call(Args) ->
@@ -81,9 +80,6 @@ handle_call(erl_compiler_options, _From, Config) ->
8180
{ reply, Opts, Config }
8281
end;
8382

84-
handle_call({ lexical, File }, _From, #elixir_code_server{lexical=Lexical} = Config) ->
85-
{ reply, orddict:find(File, Lexical), Config };
86-
8783
handle_call(_Request, _From, Config) ->
8884
{ reply, undef, Config }.
8985

@@ -128,12 +124,6 @@ handle_cast({ unload_files, Files }, Config) ->
128124
handle_cast({ return_module_name, H }, #elixir_code_server{pool={T,Counter}} = Config) ->
129125
{ noreply, Config#elixir_code_server{pool={[H|T],Counter}} };
130126

131-
handle_cast({ register_lexical, File, Pid }, #elixir_code_server{lexical=Lexical} = Config) ->
132-
{ noreply, Config#elixir_code_server{lexical=orddict:store(File, Pid, Lexical)} };
133-
134-
handle_cast({ unregister_lexical, File }, #elixir_code_server{lexical=Lexical} = Config) ->
135-
{ noreply, Config#elixir_code_server{lexical=orddict:erase(File, Lexical)} };
136-
137127
handle_cast(_Request, Config) ->
138128
{ noreply, Config }.
139129

lib/elixir/src/elixir_compiler.erl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ quoted(Forms, File) when is_binary(File) ->
3030
try
3131
put(elixir_compiled, []),
3232
elixir_lexical:run(File, fun
33-
() -> eval_forms(Forms, 1, [], elixir:scope_for_eval([{file,File}]))
33+
(Pid) ->
34+
Scope = elixir:scope_for_eval([{file,File}]),
35+
eval_forms(Forms, 1, [], Scope#elixir_scope{lexical_tracker=Pid})
3436
end),
3537
lists:reverse(get(elixir_compiled))
3638
after

lib/elixir/src/elixir_dispatch.erl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ find_import(Meta, Name, Arity, S) ->
2424

2525
case find_dispatch(Meta, Tuple, S) of
2626
{ function, Receiver } ->
27-
elixir_lexical:record_import(S#elixir_scope.file, Receiver),
27+
elixir_lexical:record_import(Receiver, S#elixir_scope.lexical_tracker),
2828
elixir_tracker:record_import(Tuple, Receiver, S#elixir_scope.module, S#elixir_scope.function),
2929
Receiver;
3030
{ macro, Receiver } ->
31-
elixir_lexical:record_import(S#elixir_scope.file, Receiver),
31+
elixir_lexical:record_import(Receiver, S#elixir_scope.lexical_tracker),
3232
elixir_tracker:record_import(Tuple, Receiver, S#elixir_scope.module, S#elixir_scope.function),
3333
Receiver;
3434
_ ->
@@ -41,7 +41,7 @@ import_function(Meta, Name, Arity, S) ->
4141
Tuple = { Name, Arity },
4242
case find_dispatch(Meta, Tuple, S) of
4343
{ function, Receiver } ->
44-
elixir_lexical:record_import(S#elixir_scope.file, Receiver),
44+
elixir_lexical:record_import(Receiver, S#elixir_scope.lexical_tracker),
4545
elixir_tracker:record_import(Tuple, Receiver, S#elixir_scope.module, S#elixir_scope.function),
4646
remote_function(Meta, Receiver, Name, Arity, S);
4747
{ macro, _Receiver } ->
@@ -63,7 +63,7 @@ require_function(Meta, Receiver, Name, Arity, S) ->
6363
case is_element(Tuple, get_optional_macros(Receiver)) of
6464
true -> false;
6565
false ->
66-
elixir_lexical:record_remote(S#elixir_scope.file, Receiver),
66+
elixir_lexical:record_remote(Receiver, S#elixir_scope.lexical_tracker),
6767
elixir_tracker:record_remote(Tuple, Receiver, S#elixir_scope.module, S#elixir_scope.function),
6868
remote_function(Meta, Receiver, Name, Arity, S)
6969
end.
@@ -77,23 +77,23 @@ dispatch_import(Meta, Name, Args, S, Callback) ->
7777

7878
case find_dispatch(Meta, Tuple, S) of
7979
{ function, Receiver } ->
80-
elixir_lexical:record_import(S#elixir_scope.file, Receiver),
80+
elixir_lexical:record_import(Receiver, S#elixir_scope.lexical_tracker),
8181
elixir_tracker:record_import(Tuple, Receiver, Module, S#elixir_scope.function),
8282
Endpoint = case (Receiver == ?builtin) andalso is_element(Tuple, in_erlang_functions()) of
8383
true -> erlang;
8484
false -> Receiver
8585
end,
8686
elixir_translator:translate_each({ { '.', Meta, [Endpoint, Name] }, Meta, Args }, S);
8787
{ import, Receiver } ->
88-
elixir_lexical:record_remote(S#elixir_scope.file, Receiver),
88+
elixir_lexical:record_remote(Receiver, S#elixir_scope.lexical_tracker),
8989
elixir_tracker:record_remote(Tuple, Receiver, S#elixir_scope.module, S#elixir_scope.function),
9090
elixir_translator:translate_each({ { '.', Meta, [Receiver, Name] }, [{require,false}|Meta], Args }, S);
9191
Result ->
9292
case do_expand_import(Meta, Tuple, Args, Module, S, Result) of
9393
{ error, noexpansion } ->
9494
Callback();
9595
{ error, internal } ->
96-
elixir_lexical:record_import(S#elixir_scope.file, ?builtin),
96+
elixir_lexical:record_import(?builtin, S#elixir_scope.lexical_tracker),
9797
elixir_tracker:record_import(Tuple, ?builtin, Module, S#elixir_scope.function),
9898
elixir_macros:translate({ Name, Meta, Args }, S);
9999
{ ok, Receiver, Tree } ->
@@ -108,7 +108,7 @@ dispatch_require(Meta, Receiver, Name, Args, S, Callback) ->
108108

109109
case (Receiver == ?builtin) andalso is_element(Tuple, in_erlang_functions()) of
110110
true ->
111-
elixir_lexical:record_remote(S#elixir_scope.file, Receiver),
111+
elixir_lexical:record_remote(Receiver, S#elixir_scope.lexical_tracker),
112112
elixir_tracker:record_remote(Tuple, Receiver, S#elixir_scope.module, S#elixir_scope.function),
113113
{ TArgs, SA } = elixir_translator:translate_args(Args, S),
114114
{ ?wrap_call(?line(Meta), erlang, Name, TArgs), SA };
@@ -117,7 +117,7 @@ dispatch_require(Meta, Receiver, Name, Args, S, Callback) ->
117117
{ error, noexpansion } ->
118118
Callback();
119119
{ error, internal } ->
120-
elixir_lexical:record_remote(S#elixir_scope.file, ?builtin),
120+
elixir_lexical:record_remote(?builtin, S#elixir_scope.lexical_tracker),
121121
elixir_tracker:record_remote(Tuple, ?builtin, S#elixir_scope.module, S#elixir_scope.function),
122122
elixir_macros:translate({ Name, Meta, Args }, S);
123123
{ ok, Receiver, Tree } ->
@@ -159,12 +159,12 @@ do_expand_import_no_local(Meta, { Name, Arity } = Tuple, Args, Module, S, Result
159159
case is_element(Tuple, in_erlang_macros()) of
160160
true -> { error, internal };
161161
false ->
162-
elixir_lexical:record_import(S#elixir_scope.file, ?builtin),
162+
elixir_lexical:record_import(?builtin, S#elixir_scope.lexical_tracker),
163163
elixir_tracker:record_import(Tuple, ?builtin, Module, S#elixir_scope.function),
164164
{ ok, ?builtin, expand_macro_named(Meta, ?builtin, Name, Arity, Args, Module, S) }
165165
end;
166166
{ macro, Receiver } ->
167-
elixir_lexical:record_import(S#elixir_scope.file, Receiver),
167+
elixir_lexical:record_import(Receiver, S#elixir_scope.lexical_tracker),
168168
elixir_tracker:record_import(Tuple, Receiver, Module, S#elixir_scope.function),
169169
{ ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, Module, S) };
170170
{ import, Receiver } ->
@@ -179,7 +179,7 @@ expand_require(Meta, ?builtin, { Name, Arity } = Tuple, Args, Module, S) ->
179179
false ->
180180
case is_element(Tuple, in_elixir_macros()) of
181181
true ->
182-
elixir_lexical:record_remote(S#elixir_scope.file, ?builtin),
182+
elixir_lexical:record_remote(?builtin, S#elixir_scope.lexical_tracker),
183183
elixir_tracker:record_remote(Tuple, ?builtin, S#elixir_scope.module, S#elixir_scope.function),
184184
{ ok, ?builtin, expand_macro_named(Meta, ?builtin, Name, Arity, Args, Module, S) };
185185
false ->
@@ -197,7 +197,7 @@ expand_require(Meta, Receiver, { Name, Arity } = Tuple, Args, Module, S) ->
197197
false ->
198198
case is_element(Tuple, get_optional_macros(Receiver)) of
199199
true ->
200-
elixir_lexical:record_remote(S#elixir_scope.file, Receiver),
200+
elixir_lexical:record_remote(Receiver, S#elixir_scope.lexical_tracker),
201201
elixir_tracker:record_remote(Tuple, Receiver, Module, Function),
202202
{ ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, Module, S) };
203203
false -> { error, noexpansion }

lib/elixir/src/elixir_import.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ import_macros(Force, Meta, Ref, Opts, S) ->
3838
S#elixir_scope.macro_macros, Existing, S),
3939
S#elixir_scope{macros=Macros, macro_macros=Temp}.
4040

41-
record_warn(Meta, Ref, Opts, #elixir_scope{file=File}) ->
41+
record_warn(Meta, Ref, Opts, S) ->
4242
Warn =
4343
case keyfind(warn, Opts) of
4444
{ warn, false } -> false;
4545
{ warn, true } -> true;
4646
false -> not lists:keymember(context, 1, Meta)
4747
end,
48-
elixir_lexical:record_import(File, Ref, ?line(Meta), Warn).
48+
elixir_lexical:record_import(Ref, ?line(Meta), Warn, S#elixir_scope.lexical_tracker).
4949

5050
%% Calculates the imports based on only and except
5151

lib/elixir/src/elixir_lexical.erl

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
%% Module responsible for tracking lexical information.
22
-module(elixir_lexical).
3-
-export([run/2, pid/1,
3+
-export([run/2,
44
record_alias/4, record_alias/2,
55
record_import/4, record_import/2,
66
record_remote/2, format_error/1
@@ -9,70 +9,57 @@
99

1010
-define(tracker, 'Elixir.Kernel.LexicalTracker').
1111

12-
pid(File) ->
13-
if_tracker(File, fun(Pid) -> Pid end).
14-
15-
%% TODO: This only works if the file is not duplicated.
16-
%% We need to store the PID in the lexical scope.
1712
run(File, Callback) ->
1813
case code:is_loaded(?tracker) of
1914
{ file, _ } ->
2015
Pid = ?tracker:start_link(),
21-
elixir_code_server:cast({ register_lexical, File, Pid }),
16+
2217
try
23-
Callback()
18+
Callback(Pid)
2419
after
25-
%% Emit the warnings
2620
warn_unused_imports(File, Pid),
27-
28-
%% Unlink and turn off tracker
29-
unlink(Pid),
30-
?tracker:stop(Pid),
31-
elixir_code_server:cast({ unregister_lexical, File })
21+
unlink(Pid), ?tracker:stop(Pid)
3222
end;
3323
false ->
34-
Callback()
24+
Callback(nil)
3525
end.
3626

3727
%% RECORD
3828

39-
record_alias(File, Module, Line, Warn) ->
40-
if_tracker(File, fun(Pid) ->
29+
record_alias(Module, Line, Warn, Ref) ->
30+
if_tracker(Ref, fun(Pid) ->
4131
?tracker:add_alias(Pid, Module, Line, Warn),
4232
true
4333
end).
4434

45-
record_import(File, Module, Line, Warn) ->
46-
if_tracker(File, fun(Pid) ->
35+
record_import(Module, Line, Warn, Ref) ->
36+
if_tracker(Ref, fun(Pid) ->
4737
?tracker:add_import(Pid, Module, Line, Warn),
4838
true
4939
end).
5040

51-
record_alias(File, Module) ->
52-
if_tracker(File, fun(Pid) ->
41+
record_alias(Module, Ref) ->
42+
if_tracker(Ref, fun(Pid) ->
5343
?tracker:alias_dispatch(Pid, Module),
5444
true
5545
end).
5646

57-
record_import(File, Module) ->
58-
if_tracker(File, fun(Pid) ->
47+
record_import(Module, Ref) ->
48+
if_tracker(Ref, fun(Pid) ->
5949
?tracker:import_dispatch(Pid, Module),
6050
true
6151
end).
6252

63-
record_remote(File, Module) ->
64-
if_tracker(File, fun(Pid) ->
53+
record_remote(Module, Ref) ->
54+
if_tracker(Ref, fun(Pid) ->
6555
?tracker:remote_dispatch(Pid, Module),
6656
true
6757
end).
6858

6959
%% HELPERS
7060

71-
if_tracker(File, Callback) ->
72-
case elixir_code_server:call({ lexical, File }) of
73-
{ ok, Pid } -> Callback(Pid);
74-
error -> false
75-
end.
61+
if_tracker(nil, _Callback) -> false;
62+
if_tracker(Pid, Callback) when is_pid(Pid) -> Callback(Pid).
7663

7764
%% ERROR HANDLING
7865

lib/elixir/src/elixir_module.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ compile(Line, Module, Block, Vars, #elixir_scope{context_modules=FileModules} =
6363
FileList = elixir_utils:characters_to_list(File),
6464

6565
check_module_availability(Line, File, Module, C),
66-
build(Line, File, Module),
66+
build(Line, File, Module, S#elixir_scope.lexical_tracker),
6767

6868
try
6969
Result = eval_form(Line, Module, Block, Vars, S),
@@ -110,7 +110,7 @@ compile(Line, Module, Block, Vars, RawS) ->
110110

111111
%% Hook that builds both attribute and functions and set up common hooks.
112112

113-
build(Line, File, Module) ->
113+
build(Line, File, Module, Lexical) ->
114114
%% Table with meta information about the module.
115115
DataTable = data_table(Module),
116116

@@ -132,7 +132,7 @@ build(Line, File, Module) ->
132132
ets:insert(DataTable, { ?acc_attr, [before_compile, after_compile, on_definition|Attributes] }),
133133
ets:insert(DataTable, { ?persisted_attr, [vsn|Attributes] }),
134134
ets:insert(DataTable, { ?docs_attr, ets:new(DataTable, [ordered_set, public]) }),
135-
ets:insert(DataTable, { ?lexical_attr, elixir_lexical:pid(File) }),
135+
ets:insert(DataTable, { ?lexical_attr, Lexical }),
136136
ets:insert(DataTable, { ?overridable_attr, [] }),
137137

138138
%% Setup other modules

0 commit comments

Comments
 (0)