2
votes

I'm trying to write the macro that generates a module:

    defmodule GenModules do
       defmacro module(name, do: body) do
           quote do
               defmodule unquote(String.to_atom(name)) do                
                   unquote(body)
               end
           end
       end
    end

What I'm missing is to how to inject the 'import' statement that would refer the module the macro will be called from?

I.e., the following code:

    defmodule Test do
      import GenModules

      module "NewModule" do
        def test_call do
            hello_world
        end
      end

      def hello_world do
        IO.puts "Hello"
      end
    end   

won't compile because hello_world function is not visible from the generated NewModule.

So I need to generate

    import Test

before the body of the module, somehow getting the name of the module the macro was called from. How do I do this?

Thank you, Boris

1

1 Answers

1
votes

To get the module your macro was called from you can use the special form __CALLER__. It contains a bunch of information, but you can extract the calling module like so:

__CALLER__.context_modules |> hd

But more generally I don't think what you want is possible - you cannot import a module before you finish defining it. For example:

defmodule A do
  defmodule B do
    import A
  end
end

results in an error:

** (CompileError) test.exs:3: module A is not loaded but was defined.
This happens because you are trying to use a module in the same context it is defined.
Try defining the module outside the context that requires it.