I’m trying to implement some features of Protobuf and I have a case: A module needs to call another module in compiling time. They are in the same file and it’s hard to ensure their order.
defmodule FakeProtobuf do
defmacro __using__(opts) do
quote do
# register_attribute fields and set fields
@before_compile FakeProtobuf
end
end
defmacro __before_compile__(_) do
# result = Enum.map(fields, fn ...)
# even Code.ensure_loaded doesn't work
result = %{bar: Bar.default}
quote do
def default do
unquote(Macro.escape(result))
end
end
end
end
defmodule Foo do
use FakeProtobuf
# field :bar, type: Bar
end
defmodule Bar do
def default do
"bar"
end
end
Some macro details related to fields are ignored in this piece of code, but the main idea is like what I said above. This code can’t be compiled because Bar is not available when Foo is compiled even when Code.ensure_loaded(Bar) is called. I need this because I want to run some code in compiling time instead of runtime to save some time.
It works if Bar is defined before Foo or in another file. But it’s hard to ensure this in protobuf generated files.
Is there anyway to solve this?






















