diff --git a/lib/elixir/include/elixir.hrl b/lib/elixir/include/elixir.hrl index c063974f17..64994fb62f 100644 --- a/lib/elixir/include/elixir.hrl +++ b/lib/elixir/include/elixir.hrl @@ -36,6 +36,24 @@ functions %% a list with functions imported from module }). +-record(elixir_env, { + module=nil, + file=nil, + line=nil, + function=nil, + context=nil, + requires, + aliases, + functions, + macros, + macro_aliases=[], + macro_functions=[], + macro_macros=[], + context_modules=[], + vars=[], + lexical_tracker=nil +}). + -record(elixir_quote, { line=nil, context=nil, diff --git a/lib/elixir/src/elixir_macros.erl b/lib/elixir/src/elixir_macros.erl index 31eac3b791..f4a1901eec 100644 --- a/lib/elixir/src/elixir_macros.erl +++ b/lib/elixir/src/elixir_macros.erl @@ -95,8 +95,8 @@ translate({defmodule, Meta, [Ref, KV]}, S) when is_list(KV) -> { TRef, S } end, - MS = FS#elixir_scope{local=nil}, - { elixir_module:translate(Meta, FRef, Block, MS), FS }; + Env = elixir_scope:to_ex_env({ ?line(Meta), FS }), + translate_each(elixir_module:translate(Ref, Block, Env), FS); translate({Kind, Meta, [Call]}, S) when ?defs(Kind) -> translate({Kind, Meta, [Call, nil]}, S); diff --git a/lib/elixir/src/elixir_module.erl b/lib/elixir/src/elixir_module.erl index 9f30303f99..e5f79731a3 100644 --- a/lib/elixir/src/elixir_module.erl +++ b/lib/elixir/src/elixir_module.erl @@ -1,5 +1,5 @@ -module(elixir_module). --export([translate/4, compile/5, data_table/1, docs_table/1, +-export([translate/3, compile/4, data_table/1, docs_table/1, eval_quoted/4, format_error/1, eval_callbacks/5]). -include("elixir.hrl"). @@ -42,21 +42,29 @@ docs_table(Module) -> %% The abstract form for extra arguments may be given and they %% will be passed to the invoked function. -translate(Meta, Ref, Block, S) -> - Line = ?line(Meta), - LexS = case S#elixir_scope.function of - nil -> S; - _ -> S#elixir_scope{lexical_tracker=nil} +translate(Ref, Block, ExEnv) -> + Env = elixir_env:from_ex(ExEnv), + + %% In case we are generating a module from inside a function, + %% we get rid of the lexical tracker information as, at this + %% point, the lexical tracker process is long gone. + LexEnv = case Env#elixir_env.function of + nil -> Env; + _ -> Env#elixir_env{lexical_tracker=nil} end, - MetaBlock = elixir_utils:elixir_to_erl(Line, Block, LexS), - { MetaS, Vars } = elixir_scope:serialize_with_vars(Line, LexS), + { Escaped, _ } = elixir_quote:escape(Block, false), + { QuotedEnv, QuotedVars } = elixir_env:to_quote_with_vars(LexEnv), - Args = [{integer, Line, Line}, Ref, MetaBlock, Vars, MetaS], - ?wrap_call(Line, ?MODULE, compile, Args). + Args = [Ref, Escaped, QuotedVars, QuotedEnv], + { { '.', [], [elixir_module, compile] }, [], Args }. %% The compilation hook. +compile(Module, Block, Vars, #elixir_env{line=Line} = Env) -> + Dict = [{ { Name, Kind }, Value } || { Name, Kind, Value, _ } <- Vars], + compile(Line, Module, Block, Vars, elixir_env:to_scope_with_vars(Env, Dict)). + compile(Line, Module, Block, Vars, #elixir_scope{context_modules=FileModules} = RawS) when is_atom(Module) -> C = elixir_compiler:get_opts(), S = case lists:member(Module, FileModules) of @@ -106,12 +114,7 @@ compile(Line, Module, Block, Vars, #elixir_scope{context_modules=FileModules} = end; compile(Line, Other, _Block, _Vars, #elixir_scope{file=File}) -> - elixir_errors:form_error(Line, File, ?MODULE, { invalid_module, Other }); - -compile(Line, Module, Block, Vars, RawS) -> - Dict = [{ { Name, Kind }, Value } || { Name, Kind, Value, _ } <- Vars], - S = elixir_scope:deserialize_with_vars(RawS, Dict), - compile(Line, Module, Block, Vars, S). + elixir_errors:form_error(Line, File, ?MODULE, { invalid_module, Other }). %% Hook that builds both attribute and functions and set up common hooks.