Create sub module with atom name

On my phone, so apologies if some of this is incorrect as I can’t test it, but I’d try the following:

defmacro sub_field(name, type, opts \\ [], do: block) do
    ast = register_struct(block, opts)

    name =
      name
      |> Atom.to_string()
      |> Macro.camelize()
      |> String.to_atom()

    quote unquote: false, bind_quoted: [name: name, ast: ast] do
      module_name = Module.concat(__MODULE__, name)

      defmodule unquote(module_name) do
        unquote(ast)
      end
    end
  end

I’d really need to test to be sure, and it can be a little tricky to follow with the nested unquote/bind_quotes bit, but essentially you need to access __MODULE__ in the calling module.