Replace Code.load_file/2 by Code.compile_file/2 (#7201)

Currently there is no way to compile a file without leaving
footprints on the system. Plus, the term load_file/2 is very
confusing as loaded is the notation used by modules.

This commit focuses the whole loaded aspect of files exclusively
on require_file/2 (and renames two functions accordingly) and
introduces compile_file/2 which is semantically simpler than
load_file/2.
This commit is contained in:
José Valim
2018-01-13 22:04:22 +01:00
committed by GitHub
parent 9d63a57d5d
commit b9591267dc
8 changed files with 227 additions and 152 deletions
+16 -21
View File
@@ -6,7 +6,7 @@
-define(timeout, 30000).
-record(elixir_code_server, {
loaded=#{},
required=#{},
mod_pool={[], 0},
mod_ets=#{},
compilation_status=#{}
@@ -24,13 +24,8 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, ok, []).
init(ok) ->
%% We attempt to load those modules here so throughout
%% the codebase we can avoid code:is_loaded/1 checks.
_ = code:ensure_loaded('Elixir.Macro.Env'),
%% The table where we store module definitions
_ = ets:new(elixir_modules, [set, protected, named_table, {read_concurrency, true}]),
{ok, #elixir_code_server{}}.
handle_call({defmodule, Pid, Tuple}, _From, Config) ->
@@ -44,20 +39,20 @@ handle_call({undefmodule, Ref}, _From, Config) ->
{reply, ok, undefmodule(Ref, Config)};
handle_call({acquire, Path}, From, Config) ->
Current = Config#elixir_code_server.loaded,
Current = Config#elixir_code_server.required,
case maps:find(Path, Current) of
{ok, true} ->
{reply, loaded, Config};
{reply, required, Config};
{ok, {Ref, List}} when is_list(List), is_reference(Ref) ->
Queued = maps:put(Path, {Ref, [From | List]}, Current),
{reply, {queued, Ref}, Config#elixir_code_server{loaded=Queued}};
{reply, {queued, Ref}, Config#elixir_code_server{required=Queued}};
error ->
Queued = maps:put(Path, {make_ref(), []}, Current),
{reply, proceed, Config#elixir_code_server{loaded=Queued}}
{reply, proceed, Config#elixir_code_server{required=Queued}}
end;
handle_call(loaded, _From, Config) ->
{reply, [F || {F, true} <- maps:to_list(Config#elixir_code_server.loaded)], Config};
handle_call(required, _From, Config) ->
{reply, [F || {F, true} <- maps:to_list(Config#elixir_code_server.required)], Config};
handle_call({compilation_status, CompilerPid}, _From, Config) ->
CompilationStatusList = Config#elixir_code_server.compilation_status,
@@ -91,24 +86,24 @@ handle_cast({reset_warnings, CompilerPid}, Config) ->
CompilationStatusNew = maps:put(CompilerPid, ok, CompilationStatusCurrent),
{noreply, Config#elixir_code_server{compilation_status=CompilationStatusNew}};
handle_cast({loaded, Path}, Config) ->
Current = Config#elixir_code_server.loaded,
handle_cast({required, Path}, Config) ->
Current = Config#elixir_code_server.required,
case maps:find(Path, Current) of
{ok, true} ->
{noreply, Config};
{ok, {Ref, List}} when is_list(List), is_reference(Ref) ->
_ = [Pid ! {elixir_code_server, Ref, loaded} || {Pid, _Tag} <- lists:reverse(List)],
_ = [Pid ! {elixir_code_server, Ref, required} || {Pid, _Tag} <- lists:reverse(List)],
Done = maps:put(Path, true, Current),
{noreply, Config#elixir_code_server{loaded=Done}};
{noreply, Config#elixir_code_server{required=Done}};
error ->
Done = maps:put(Path, true, Current),
{noreply, Config#elixir_code_server{loaded=Done}}
{noreply, Config#elixir_code_server{required=Done}}
end;
handle_cast({unload_files, Files}, Config) ->
Current = Config#elixir_code_server.loaded,
Unloaded = maps:without(Files, Current),
{noreply, Config#elixir_code_server{loaded=Unloaded}};
handle_cast({unrequire_files, Files}, Config) ->
Current = Config#elixir_code_server.required,
Unrequired = maps:without(Files, Current),
{noreply, Config#elixir_code_server{required=Unrequired}};
handle_cast({return_compiler_module, H}, #elixir_code_server{mod_pool={T, Counter}} = Config) ->
{noreply, Config#elixir_code_server{mod_pool={[H | T], Counter}}};