Iām not really familiar with compiler internals, but my guess is that technically, defmodule
macro is properly invoked. Iād also guess that the macro successfully returns a quoted block, but IEx then tries to evaluate that block, and thatās where things break. I suspect they break b/c during the module compilation the code inside the do block is evaluated (expanded), and at this point we are trying to invoke unquote
outside of a macro context (because macro has already returned).
I mostly base my suspicion by looking at the stacktrace of the following iex session:
iex> :erlang.system_flag(:backtrace_depth, 20)
iex> try do
defmodule Foo do unquote(1) end
catch _,_ ->
IO.inspect :erlang.get_stacktrace
end
Which gives me:
[{:elixir_exp, :expand, 2, [file: 'src/elixir_exp.erl', line: 10]},
{:elixir_exp, :expand_block, 4, [file: 'src/elixir_exp.erl', line: 448]},
{:elixir_exp, :expand, 2, [file: 'src/elixir_exp.erl', line: 39]},
{:elixir, :quoted_to_erl, 3, [file: 'src/elixir.erl', line: 255]},
{:elixir_compiler, :code_loading_compilation, 3,
[file: 'src/elixir_compiler.erl', line: 72]},
{:elixir_module, :eval_form, 6, [file: 'src/elixir_module.erl', line: 191]},
{:elixir_module, :do_compile, 5, [file: 'src/elixir_module.erl', line: 71]},
{:elixir_lexical, :run, 3, [file: 'src/elixir_lexical.erl', line: 17]},
{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 670]},
{:erl_eval, :try_clauses, 8, [file: 'erl_eval.erl', line: 904]},
{:elixir, :erl_eval, 3, [file: 'src/elixir.erl', line: 224]},
{:elixir, :eval_forms, 4, [file: 'src/elixir.erl', line: 212]},
{IEx.Evaluator, :handle_eval, 6, [file: 'lib/iex/evaluator.ex', line: 182]},
{IEx.Evaluator, :do_eval, 4, [file: 'lib/iex/evaluator.ex', line: 175]},
{IEx.Evaluator, :eval, 4, [file: 'lib/iex/evaluator.ex', line: 155]},
{IEx.Evaluator, :loop, 3, [file: 'lib/iex/evaluator.ex', line: 61]},
{IEx.Evaluator, :init, 4, [file: 'lib/iex/evaluator.ex', line: 21]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]
To me, that proves that my code is in fact successfully compiled and executed. Otherwise, the try
block wouldnāt even run, and I wouldnāt be able to catch the error. Therefore, the error happens when the quoted block returned by defmodule
is interpreted.
But thatās a lot of guesswork on my behalf, so letās ping @josevalim for a precise explanation 